我知道在 C 中的函数内声明静态变量意味着该变量在函数调用之间保留其状态。在线程的上下文中,这是否会导致变量在多个线程上保留其状态,或者在每个线程之间具有单独的状态? 这是我正在努力回答的过去的纸质考试问题:
以下 C 函数旨在用于为其调用者分配唯一标识符 (UID):解释 get_uid() 在多线程调用的环境中可能会以何种方式错误地工作。使用 具体的示例场景,给出关于原因和方式的具体细节 可能会出现不正确的行为。
get_uid() { static int i = 0; return i++; }
目前我假设每个线程都有一个单独的变量状态,但我不确定这是否正确,或者答案是否更多地与缺乏互斥有关。如果是这样的话,那么在这个例子中如何实现信号量呢?
get_uid()
,可能存在
竞争条件,哪些线程会递增
i
并获取可能不唯一的ID。i
是静态变量,因此它有固定的地址。它的“状态”只是该地址处的内存内容,由所有线程共享。
后缀
++
运算符递增其参数并生成递增之前的参数值。这些操作的完成顺序没有定义。一种可能的实现是
copy i to R1
copy R1 to R2
increment R2
copy R2 to i
return R1
如果有多个线程正在运行,它们可以同时或分散执行这些指令。自己计算出可以获得不同结果的序列。 (请注意,每个线程确实有自己的寄存器状态,即使对于在同一 CPU 上运行的线程也是如此,因为当线程切换时会保存和恢复寄存器。)
这种根据不同线程中不确定的操作顺序而产生不同结果的情况称为“竞争条件”,因为不同线程之间存在“竞争”,即哪个线程先执行哪个操作。
不,如果您想要一个值取决于使用它的线程的变量,您应该看看
线程本地存储。如果您使用 gcc,则可以使用 atomic 内置