C语言 静态变量和线程 (C)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15857732/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Static Variables and Threads (C)
提问by dahui
I know that declaring a static variable within a function in C means that this variable retains its state between function invocations. In the context of threads, will this result in the variable retaining its state over multiple threads, or having a separate state between each thread?
我知道在 C 中的函数中声明一个静态变量意味着该变量在函数调用之间保持其状态。在线程的上下文中,这会导致变量在多个线程上保持其状态,还是在每个线程之间具有单独的状态?
Here is a past paper exam question I am struggling to answer:
这是我正在努力回答的过去的纸考试题:
The following C function is intended to be used to allocate unique identifiers (UIDs) to its callers:
get_uid() { static int i = 0; return i++; }Explain in what way get_uid() might work incorrectly in an environment where it is being called by multiple threads. Using a specific example scenario, give specific detail on why and how such incorrect behaviour might occur.
以下 C 函数旨在用于为其调用者分配唯一标识符 (UID):
get_uid() { static int i = 0; return i++; }解释 get_uid() 在被多个线程调用的环境中可能以何种方式不正确地工作。使用特定的示例场景,详细说明这种不正确行为可能发生的原因和方式。
At the moment I am assuming that each thread has a separate state for the variable, but I am not sure if that is correct or if the answer is more to do with the lack of mutual exclusion. If that is the case then how could semaphores be implemented in this example?
目前我假设每个线程都有一个单独的变量状态,但我不确定这是否正确,或者答案是否更多地与缺乏互斥有关。如果是这样,那么在这个例子中如何实现信号量?
回答by P.P
Your assumption (threads have their own copy) is not correct. The main problem with code is when multiple threads call that function get_uid(), there's a possible race conditionas to which threads increments iand gets the ID which may not be unique.
您的假设(线程有自己的副本)是不正确的。代码的主要问题是当多个线程调用该函数时get_uid(),可能存在 竞争条件,即哪些线程会增加i并获取可能不唯一的 ID。
回答by Jim Balter
All the threads of a process share the same address space. Since iis a static variable, it has a fixed address. Its "state" is just the content of the memory at that address, which is shared by all the threads.
一个进程的所有线程共享相同的地址空间。由于i是一个静态变量,它有一个固定的地址。它的“状态”只是该地址处的内存内容,由所有线程共享。
The postfix ++operator increments its argument and yields the value of the argument before the increment. The order in which these are done is not defined. One possible implementation is
后缀++运算符递增其参数并在递增之前产生参数的值。这些完成的顺序没有定义。一种可能的实现是
copy i to R1
copy R1 to R2
increment R2
copy R2 to i
return R1
If more than one thread is running, they can both be executing these instructions simultaneously or interspersed. Work out for yourself sequences where various results obtain. (Note that each thread does have its own register state, even for threads running on the same CPU, because registers are saved and restored when threads are switched.)
如果有多个线程在运行,它们可以同时或分散执行这些指令。为自己制定获得各种结果的序列。(请注意,每个线程都有自己的寄存器状态,即使对于运行在同一 CPU 上的线程也是如此,因为在切换线程时会保存和恢复寄存器。)
A situation like this where there are different results depending on the indeterministic ordering of operations in different threads is called a race condition, because there's a "race" among the different threads as to which one does which operation first.
这种根据不同线程中操作的不确定顺序而产生不同结果的情况称为竞争条件,因为不同线程之间存在“竞争”,即哪个线程首先执行哪个操作。
回答by Stephane Rolland
No, if you want a variable which value depends upon the thread in which it is used, you should have a look at Thread Local Storage.
不,如果您想要一个值取决于使用它的线程的变量,您应该查看线程本地存储。
A static variable, you can imagine it really like a completely global variable. It's really much the same. So it's shared by the whole system that knows its address.
一个静态变量,你可以想象它真的像一个完全全局的变量。这真的是一样的。因此,它由知道其地址的整个系统共享。
EDIT: also as a comment reminds it, if you keep this implementation as a static variable, race conditions could make that the value iis incremented at the same time by several threads, meaning that you don't have any idea of the value which will be returned by the function calls. In such cases, you should protect access by so called synchronization objects like mutexesor critical sections.
编辑:还有一条评论提醒它,如果您将此实现保留为静态变量,竞争条件可能会使i多个线程同时增加该值,这意味着您不知道将要使用的值由函数调用返回。在这种情况下,您应该通过所谓的同步对象(如互斥锁或临界区)来保护访问。
回答by John Szakmeister
Since this looks like homework, I'll answer only part of this and that is each thread will share the same copy of i. IOW, threads do not get their own copies. I'll leave the mutual exclusion bit to you.
由于这看起来像作业,我将只回答其中的一部分,即每个线程将共享相同的i. IOW,线程不会获得自己的副本。我将把互斥位留给你。
回答by nommyravian
Each thread will share the same static variable which is mostly likely a global variable. The scenario where some threads can have wrong value is the race condition (increment isn't done in one single execution rather it is done in 3 assembly instructions, load, increment, store). Read here and the diagram at the link explains it well.
每个线程将共享相同的静态变量,这很可能是一个全局变量。某些线程可能具有错误值的情况是竞争条件(增量不是在一次执行中完成,而是在 3 个汇编指令中完成,加载、增量、存储)。在这里阅读,链接中的图表很好地解释了它。
回答by Sam
If you are using gcc you can use the atomic builtinfunctions. I'm not sure what is available for other compilers.
如果您使用 gcc,您可以使用原子内置函数。我不确定其他编译器有什么可用的。
int get_uid()
{
static int i = 0;
return __atomic_fetch_add(&i, 1, __ATOMIC_SEQ_CST);
}
This will ensure that the variable cannot be acted on by more than one thread at a time.
这将确保变量不能同时被多个线程操作。

