[c++] 函數靜態變量是否在GCC中是線程安全的?


Answers

我們對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無法正確的事實也很明顯)

Question

在示例代碼中

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

使用GCC編譯是否可以保證以線程安全的方式創建和初始化b

在gcc的手冊頁中,找到了-fno-threadsafe-statics命令行選項:

不要發出額外的代碼來使用C ++ ABI中指定的例程來進行本地靜態的線程安全初始化。 您可以使用此選項在不需要線程安全的代碼中略微減小代碼大小。

  1. 這是否意味著,默認情況下,GCC的本地靜態是線程安全的? 所以沒有理由用pthread_mutex_lock/unlock來明確保護?

  2. 如何編寫可移植代碼 - 如何檢查編譯器是否會添加其防護? 或者關閉GCC的這個功能是否更好?




我認為關鍵詞是

...本地靜態的線程安全初始化

我讀到這意味著它只是以線程安全的方式完成靜態的初始化。 靜態的一般使用不是線程安全的。




Links