在GCC中,函数静态变量是否是线程安全的?

在示例代码中

void foo()
{
  static Bar b;
  ...
}

用GCC编译是否可以保证以线程安全的方式创建和初始化b

在gcc的手册页中,找到-fno-threadsafe-statics命令行选项:

不要发出多余的代码来使用   在C ++ ABI中为   局部线程安全初始化   静力学 您可以使用此选项   在代码中稍微减少代码大小   不需要是线程安全的。

  1. 这是否意味着GCC默认情况下局部静态变量是线程安全的? 因此没有理由采取明确的保护措施,例如 与pthread_mutex_lock/unlock吗?

  2. 如何编写可移植的代码-如何检查编译器是否将添加其防护措施? 还是最好关闭GCC的此功能?

CsTamas asked 2019-10-09T17:50:11Z
4个解决方案
42 votes
  1. 不,这意味着本地statics的初始化是线程安全的。

  2. 您肯定要启用此功能。 本地statics的线程安全初始化非常重要。 如果通常需要对本地statics进行线程安全访问,则需要自己添加适当的防护。

CB Bailey answered 2019-10-09T17:50:29Z
17 votes

GCC 3.4生成的用于保护本地静态初始化的锁定代码存在严重问题。 该版本使用了全局共享的互斥锁来保护所有静态初始化,从而导致代码死锁。 我们从一个函数的结果初始化了一个局部静态变量,该函数启动了另一个线程,该线程创建了一个局部静态变量。 伪代码:

voif f()
{
  static int someValue = complexFunction();
  ...
}
int complexFunction()
{
  start_thread( threadFunc() );
  wait_for_some_input_from_new_thread();
  return input_from_new_thread;
}
void threadFunc()
{
  static SomeClass s();
  ...
}

唯一的解决方案是禁用gcc的此功能。 如果您需要代码具有可移植性(就像我们所做的那样),则无论如何您都不能依赖特定gcc版本中添加的功能来确保线程安全。 据说C ++ 0x添加了线程安全的局部静态变量,直到那之前这是非标准的魔术,这使您的代码不可移植,因此我建议您这样做。如果决定使用它,建议编写一个示例应用程序,以验证您的gcc版本没有为此目的使用单个全局互斥锁。 (线程安全的困难从即使gcc都无法正确实现这一事实显而易见)

shojtsy answered 2019-10-09T17:51:02Z
6 votes

这实际上并不能立即回答您的问题(Charles已经做到了),但是我认为是时候再次发布指向本文的链接了。 它为全局变量的初始化提供了亮点,所有尝试在多线程环境中使用static变量的人都应该阅读并理解它。

sbi answered 2019-10-09T17:51:27Z
5 votes

我认为关键是

...的线程安全初始化   局部静力学。

我将其理解为意味着只能以线程安全的方式完成静态的初始化。 静态的一般用法不是线程安全的。

Stephen C answered 2019-10-09T17:52:05Z
translate from https://stackoverflow.com:/questions/1270927/are-function-static-variables-thread-safe-in-gcc