所以环顾互联网,我找不到关于此的一致且有用的信息。那么问题来了:
为什么说 C 中的局部静态变量是线程不安全的?我的意思是,静态局部变量存储在所有线程共享的数据段中,但是内部链接不应该阻止线程进入彼此的静态变量吗?
This论坛帖子似乎暗示线程实际上偶尔会进入彼此的数据段,但这种行为不会明显违反自 90 年代以来的所有 c 标准吗?如果这种行为是可以预料到的,那么数据段的使用(即所有具有静态存储持续时间的变量,包括全局变量)是否早就在连续的 c 标准中被弃用了?
我真的不明白这一点,因为每个人似乎都反对局部静态变量,但人们似乎无法就原因达成一致,研究一些论点表明他们构思不当。
一方面,我认为局部静态变量是在函数调用之间传递信息的一种非常好的方式,它可以真正提高可读性和限制范围(相比之下,将信息作为参数传递并写回每个函数调用)。
据我所知,局部静态变量的使用是完全合法的。但也许我错过了什么?我真的很想知道情况是否如此。
[编辑]:这里的答案非常有帮助。感谢大家的见解。
最佳答案
but isn't internal linkage supposed to stop threads from stepping in each other's static variables?
不,链接与线程安全无关。它只是限制函数访问在其他作用域中声明的变量,这是一个不同且无关的问题。
假设您有这样一个函数:
int do_stuff (void)
{
static int x=0;
...
return x++;
}
然后这个函数被多个线程调用,线程1和线程2。线程回调函数无法访问x
直接,因为它有本地范围。但是,他们可以调用 do_stuff()
他们可以同时这样做。然后你会得到这样的场景:
- 线程 1 已执行
do_stuff
直到点返回0
给来电者。 - 线程 1 即将写入值
1
至x
, 但在此之前..: - 上下文切换,线程2介入并执行
do_stuff
. - 线程 2 读取
x
, 它仍然是0
, 所以它返回0
给调用者然后增加x
通过1
. -
x
现在是1
. - 线程 1 再次获得焦点。它正要存储
1
至x
这就是它的作用。 - 现在
x
还是1
, 尽管如果程序运行正确,它应该是2
.
当访问 x
时,情况会变得更糟在多条指令中完成,因此一个线程读取“x
的一半”然后被中断。
这是一个“竞争条件”,这里的解决方案是保护 x
具有互斥锁或类似的保护机制。这样做将使函数线程安全。或者,do_stuff
可以重写为不使用任何静态存储变量或类似资源 - 然后它将可重入。
关于c - c中的局部静态变量线程如何不安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50796033/