Являются ли статические переменные функции потокобезопасными в GCC?


В примере кода

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

составлен с GCC гарантируется ли, что b будет создан и инициализирован потокобезопасным способом ?

в справочной странице gcc, нашел - fno-threadsafe-statics параметр командной строки:

не выдавайте дополнительный код для использования подпрограммы, указанные в C++ ABI для потокобезопасной инициализации местных статика. Вы можете использовать эту опцию для уменьшить размер кода немного в коде не нужно быть потокобезопасным.

  1. означает ли это, что локальная статика является потокобезопасной по умолчанию с GCC ? Поэтому нет причин ставить явную охрану, например, с pthread_mutex_lock/unlock ?

  2. Как написать портативный код - как проверить, если компилятор добавит свои охранники ? Или лучше отключить эту функцию GCC ?

4 57

4 ответа:

  1. нет, это значит, что инициализации местных statics является потокобезопасным.

  2. вы определенно хотите оставить эту функцию включенной. Потокобезопасной инициализации местных statics очень важно. Если вам нужен вообще потокобезопасный доступ к local statics тогда вам нужно будет добавить соответствующие охранники самостоятельно.

у нас были серьезные проблемы с кодом блокировки, сгенерированным 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 не может получить это право)

Это на самом деле не отвечает на ваши вопросы сразу (Чарльз уже сделал это), но я думаю, что пришло время разместить ссылку на в этой статье еще раз. Он проливает свет на инициализацию глобалов и должен быть прочитан и понят всеми, кто пытается использовать static переменные в многопоточной среде.

Я думаю, что ключевая фраза

... потокобезопасный инициализации of локальная статика.

Я прочитал это как означающее, что это только инициализация статики, которая будет выполнена потокобезопасным способом. Общее использование статики не будет потокобезопасным.