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

时间:2022-08-11 11:47:37

In the example code

在示例代码中

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

compiled with GCC is it guaranteed that b will be created and initialized in a thread-safe manner ?

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

In gcc's man page, found the -fno-threadsafe-statics command line option:

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

Do not emit the extra code to use the routines specified in the C++ ABI for thread-safe initialization of local statics. You can use this option to reduce code size slightly in code that doesn't need to be thread-safe.

不要发出额外的代码来使用c++ ABI中为本地静态的线程安全初始化指定的例程。您可以使用此选项在不需要线程安全的代码中稍微减少代码的大小。

  1. Does it mean, that local statics are thread-safe by default with GCC ? So no reason to put explicit guarding e.g. with pthread_mutex_lock/unlock ?

    它的意思是,默认情况下,本地静态线程是线程安全的吗?所以没有理由用pthread_mutex_lock/unlock进行显式的保护?

  2. How to write portable code - how to check if compiler will add its guards ? Or is it better to turn off this feature of GCC ?

    如何编写可移植的代码——如何检查编译器是否会添加它的保护?还是关闭GCC的这个特性更好?

4 个解决方案

#1


42  

  1. No, it means that the initialization of local statics is thread-safe.

    不,这意味着本地静态的初始化是线程安全的。

  2. You definitely want to leave this feature enabled. Thread-safe initialization of local statics is very important. If you need generally thread-safe access to local statics then you will need to add the appropriate guards yourself.

    您肯定希望保留这个特性。局部静态的线程安全初始化是非常重要的。如果您需要通常线程安全的访问本地静态,那么您需要自己添加适当的保护。

#2


17  

We had serious issues with the locking code generated by GCC 3.4 to protect local static initialization. That version used a global shared mutex to protect all and any static initialization which lead to a deadlock in our code. We had a local static variable initialized from a result of a function, which started another thread, which created a local static variable. Pseudocode:

为了保护本地静态初始化,我们对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();
  ...
}

The only solution was to disable this feature of gcc. If you need your code to be portable , which we did, you can not anyway depend on a feature added in a specific gcc version for thread safety. Supposedly C++0x adds thread-safe local statics, until then this is non-standard magic which makes your code non-portable, so I am advising against it. If you decide to use it, I suggest you validate that your gcc version does not use a single global mutex for this purpose by writing a sample application. (The difficulty of thread-safety is apparent from the fact that even gcc can not get it right)

唯一的解决方案是禁用gcc的这个特性。如果您需要您的代码是可移植的(我们已经这么做了),您就不能依赖于在特定的gcc版本中添加的特性来保证线程安全。假设c++ 0x增加了线程安全的本地静态,在此之前,这是一种非标准的魔法,使您的代码不可移植,所以我建议不要这么做。如果您决定使用它,我建议您通过编写示例应用程序来验证您的gcc版本没有为此使用一个全局互斥对象。(线程安全的困难很明显,因为即使gcc也做不好)

#3


6  

This is not really answering your questions straight away (Charles already did that), but I think it's time to post a link to this article again. It throws light on the initialization of globals and should be read and understood by everyone attempting to use static variables in a multi-threaded environment.

这并不是直接回答你的问题(Charles已经这么做了),但我认为是时候再次发布这篇文章的链接了。它阐明了全局变量的初始化,应该被所有试图在多线程环境中使用静态变量的人阅读和理解。

#4


5  

I think that the key phrase is

我认为关键的短语是。

... thread-safe initialization of local statics.

…本地静态的线程安全初始化。

I read this as meaning that it is only initialization of statics that would be done in a thread-safe way. General use of statics would not be thread-safe.

我将其理解为,这只是静态的初始化,可以用线程安全的方式完成。一般使用静态不会是线程安全的。

#1


42  

  1. No, it means that the initialization of local statics is thread-safe.

    不,这意味着本地静态的初始化是线程安全的。

  2. You definitely want to leave this feature enabled. Thread-safe initialization of local statics is very important. If you need generally thread-safe access to local statics then you will need to add the appropriate guards yourself.

    您肯定希望保留这个特性。局部静态的线程安全初始化是非常重要的。如果您需要通常线程安全的访问本地静态,那么您需要自己添加适当的保护。

#2


17  

We had serious issues with the locking code generated by GCC 3.4 to protect local static initialization. That version used a global shared mutex to protect all and any static initialization which lead to a deadlock in our code. We had a local static variable initialized from a result of a function, which started another thread, which created a local static variable. Pseudocode:

为了保护本地静态初始化,我们对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();
  ...
}

The only solution was to disable this feature of gcc. If you need your code to be portable , which we did, you can not anyway depend on a feature added in a specific gcc version for thread safety. Supposedly C++0x adds thread-safe local statics, until then this is non-standard magic which makes your code non-portable, so I am advising against it. If you decide to use it, I suggest you validate that your gcc version does not use a single global mutex for this purpose by writing a sample application. (The difficulty of thread-safety is apparent from the fact that even gcc can not get it right)

唯一的解决方案是禁用gcc的这个特性。如果您需要您的代码是可移植的(我们已经这么做了),您就不能依赖于在特定的gcc版本中添加的特性来保证线程安全。假设c++ 0x增加了线程安全的本地静态,在此之前,这是一种非标准的魔法,使您的代码不可移植,所以我建议不要这么做。如果您决定使用它,我建议您通过编写示例应用程序来验证您的gcc版本没有为此使用一个全局互斥对象。(线程安全的困难很明显,因为即使gcc也做不好)

#3


6  

This is not really answering your questions straight away (Charles already did that), but I think it's time to post a link to this article again. It throws light on the initialization of globals and should be read and understood by everyone attempting to use static variables in a multi-threaded environment.

这并不是直接回答你的问题(Charles已经这么做了),但我认为是时候再次发布这篇文章的链接了。它阐明了全局变量的初始化,应该被所有试图在多线程环境中使用静态变量的人阅读和理解。

#4


5  

I think that the key phrase is

我认为关键的短语是。

... thread-safe initialization of local statics.

…本地静态的线程安全初始化。

I read this as meaning that it is only initialization of statics that would be done in a thread-safe way. General use of statics would not be thread-safe.

我将其理解为,这只是静态的初始化,可以用线程安全的方式完成。一般使用静态不会是线程安全的。