在示例代码中
void foo()
{
static Bar b;
...
}
使用 GCC 编译,是否可以保证以线程安全的方式创建和初始化b
?
在gcc的手册页中,找到了 -fno-threadsafe-statics 命令行选项:
不要发出额外的代码来使用 在C ++ ABI中指定的例程 本地的线程安全初始化 静。您可以使用此选项 在代码中略微减少代码大小 不需要是线程安全的。
这是否意味着,默认情况下GCC的本地静态是线程安全的?因此没有理由明确保护,例如与pthread_mutex_lock/unlock
?
如何编写可移植代码 - 如何检查编译器是否会添加其防护?或者关闭GCC的这个功能是否更好?
答案 0 :(得分:42)
不,这意味着本地static
的初始化是线程安全的。
您肯定希望启用此功能。本地static
的线程安全初始化非常重要。如果您通常需要线程安全访问本地static
,那么您需要自己添加适当的防护。
答案 1 :(得分:17)
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也无法做到正确)
答案 2 :(得分:6)
这并不是马上回答你的问题(Charles already did that),但我认为是时候再次发布this article的链接了。它揭示了全局变量的初始化,每个试图在多线程环境中使用static
变量的人都应该阅读并理解它。
答案 3 :(得分:5)
我认为关键词是
...线程安全的初始化 当地的静电。
我读到这意味着它只是以线程安全的方式完成静态的初始化。静态的一般用法不是线程安全的。