静态变量和线程(C)(Static Variables and Threads (C))

2019-08-20 02:54发布

我知道,在C的函数中声明的静态变量意味着该变量保留功能调用之间的状态。 在线程的上下文中,将这个结果在可变保持其状态在多个线程,或具有每个线程之间的单独的状态?

这是过去纸考试的问题,我很努力地回答:

下面的C函数旨在被用于分配唯一标识符(UID的)到它的调用者:

 get_uid() { static int i = 0; return i++; } 

说明以何种方式get_uid()可能会在一个环境中工作不正确的地方是被多个线程调用。 用一个具体的例子情况下,给出的原因和如何可能会发生这种不正确的行为的具体细节。

目前,我假设每个线程都有一个变量一个独立的国家,但我不知道这是正确的,或者如果答案是更多的是与缺乏相互排斥的。 如果是这样的话,那么如何能信号灯在这个例子中实现?

Answer 1:

您的假设(线程都有自己的副本)是不正确的。 与代码的主要问题是,当多个线程中调用该函数get_uid()有一个可能的竞争条件哪个线程递增i ,并得到其可能不是唯一的ID。



Answer 2:

All the threads of a process share the same address space. Since i is 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.

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.)

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.



Answer 3:

不,如果你想要的值取决于使用它的线程的变量,你应该看看线程本地存储。

静态变量,你可以想像它真的像一个完全全局变量。 这真是大同小异。 所以,它是由一个知道其地址整个系统共享。

编辑 :也可以作为一个评论提醒它,如果你保持这个实现是一个静态变量,竞争条件可能使该值i在多个线程同时递增,这意味着你没有价值的任何想法,这将通过函数调用返回。 在这种情况下,你应该保护通过像所谓的同步对象的访问互斥体或临界区 。



Answer 4:

因为这看起来像功课,我会回答这只是一部分,是每个线程将共享相同的副本i 。 IOW,线程没有得到自己的副本。 我将离开互斥位给你。



Answer 5:

每个线程将共享同一个静态变量,这是最有可能的全局变量。 其中一些线程可以有错误的值的情况是比赛条件(增量不会在一个单一的执行,而它是在3汇编指令,负载,增量所做的一切,商店)。 读到这里,并在链接图解释得很好。

竞争条件



Answer 6:

如果你正在使用gcc,你可以使用原子内置功能。 我不知道什么是可为其他编译器。

int get_uid() 
{
    static int i = 0;
    return __atomic_fetch_add(&i, 1, __ATOMIC_SEQ_CST);
}

这将确保该变量不能由一个以上的线程在同一时间采取行动。



文章来源: Static Variables and Threads (C)