Являются ли функции статических переменных потокобезопасными в GCC?
В примере кода
void foo()
{
static Bar b;
...
}
скомпилированный с GCC, гарантировано, что b
будет создан и инициализирован поточно-безопасным способом?
На странице gcc man найдите опцию командной строки -fno-threadsafe-statics:
Не используйте дополнительный код для использования подпрограмм, указанных в С++ ABI для поточно-безопасная инициализация локальных статика. Вы можете использовать этот параметр для немного уменьшите размер кода в коде, который не нуждается в потокобезопасности.
-
Означает ли это, что локальная статика по умолчанию защищена потоками GCC? Поэтому нет оснований для явной защиты, например. с pthread_mutex_lock/unlock
?
-
Как написать переносимый код - как проверить, добавит ли компилятор его охранники? Или лучше отключить эту функцию GCC?
Ответы
Ответ 1
-
Нет, это означает, что инициализация локального static
является потокобезопасной.
-
Вы определенно хотите оставить эту функцию включенной. Инициализация потоков локальных static
очень важна. Если вам нужен потокобезопасный доступ к локальному static
, вам нужно будет добавить соответствующие защитники самостоятельно.
Ответ 2
У нас были серьезные проблемы с кодом блокировки, сгенерированным 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 для обеспечения безопасности потоков. Предположительно, С++ 0x добавляет поточную локальную статистику, до тех пор это нестандартная магия, которая делает ваш код не переносимым, поэтому я советую против него.
Если вы решите использовать его, я предлагаю вам проверить, что ваша версия gcc не использует один глобальный мьютекс для этой цели, написав пример приложения. (Трудность защиты потоков очевидна из-за того, что даже gcc не может понять это правильно)
Ответ 3
Это на самом деле не отвечает на ваши вопросы сразу (Charles уже сделал это), но я думаю, что пришло время опубликовать ссылку на в этой статье. Он проливает свет на инициализацию глобалов и должен быть прочитан и понят всем, кто пытается использовать переменные static
в многопоточной среде.
Ответ 4
Я думаю, что ключевая фраза
... потокобезопасная инициализация локальная статика.
Я читал это как означающий, что это только инициализация статики, которая будет выполняться поточно-безопасным способом. Общее использование статики не будет потокобезопасным.