首页 > 解决方案 > c语言中的局部静态变量线程如何不安全?

问题描述

因此,环顾互联网,我找不到关于此的一致且有用的信息。那么问题来了:

为什么说 C 中的局部静态变量是线程不安全的?我的意思是,静态局部变量存储在数据段中,由所有线程共享,但内部链接不应该阻止线程进入彼此的静态变量吗?

这篇论坛帖子似乎暗示线程实际上偶尔会跨入彼此的数据段,但这种行为不会明显违反自 90 年代以来的所有 c 标准吗?如果这种行为是意料之中的,那么数据段的使用(即所有具有静态存储持续时间的变量,包括全局变量)是否早就在后续的 c 标准中被弃用了?

我真的不明白这一点,因为每个人似乎都反对局部静态变量,但人们似乎无法就原因达成一致,研究一些论点表明他们构思不周。

一方面,我认为局部静态变量是在函数调用之间传递信息的一种非常好的方式,它可以真正提高可读性和限制范围(例如,将信息作为参数传递并在每个函数调用中写回) .

据我所知,局部静态变量的使用完全合法。但也许我错过了什么?我真的很想知道是不是这样。

[编辑]:这里的答案非常有帮助。感谢大家的洞察力。

标签: cmultithreadingstaticthread-safety

解决方案


但是内部链接不应该阻止线程介入彼此的静态变量吗?

不,链接与线程安全无关。它只是限制函数访问在其他范围内声明的变量,这是一个不同且不相关的问题。

假设您有这样的功能:

int do_stuff (void)
{
  static int x=0;
  ...
  return x++;
}

然后这个函数被多个线程调用,线程1和线程2。线程回调函数不能x直接访问,因为它有本地作用域。但是,他们可以调用do_stuff()并且可以同时调用。然后你会得到这样的场景:

  • 线程 1 已经执行do_stuff,直到点返回0给调用者。
  • 线程 1 即将向 写入值1x但在此之前......:
  • 上下文切换,线程 2 介入并执行do_stuff
  • 线程 2 读取x,它仍然是0,所以它返回0给调用者,然后x增加1.
  • x现在是1
  • 线程 1 再次获得焦点。它即将存储1到,x所以它就是这样做的。
  • 现在x仍然是1,尽管如果程序表现正确,它应该是2

当访问x是在多条指令中完成时,情况会变得更糟,以至于一个线程读取“一半x”然后被中断。

这是一个“竞争条件”,这里的解决方案是x使用互斥锁或类似的保护机制进行保护。这样做将使函数thread-safe。或者,do_stuff可以重写为不使用任何静态存储变量或类似资源 - 然后它将是可重入的


推荐阅读