Об использовании статической переменной const в многопоточной среде - PullRequest
6 голосов
/ 05 марта 2012

Я пытаюсь понять потенциальный сценарий и определить, может ли это быть проблемой.

Итак, у меня есть статическая функция, которая в настоящее время является поточно-ориентированной. Функция выглядит так:

static thread_safe_func()
{
    ... process
}

Теперь в эту функцию я добавляю следующее:

static thread_safe_func()
{
  static const Class::NonThreadSafeClassName() *array[16] = {
    Class::NonThreadSafeClassName(),
    Class::NonThreadSafeClassName(),
    Class::NonThreadSafeClassName(),
    Class::NonThreadSafeClassName(),
    Class::NonThreadSafeClassName(),
    Class::NonThreadSafeClassName(),
    Class::NonThreadSafeClassName(),
  }
  ... code continues here
}

Теперь это само по себе потокобезопасно? Массив будет инициализирован один раз в течение всей продолжительности жизни приложения, поэтому после того, как функция thread_safe_func () будет вызвана и полностью запущена, я ожидаю, что она будет потоко-безопасной.

Проблема, очевидно, в том, что могло произойти во время первых звонков, что произойдет в сценарии, где поток вызывает thread_safe_func (), происходит инициализация массива const, но до завершения инициализации другой поток вызывает thread_safe_func ().

Будет ли изменение на:

static ClassMutex lock = ClassMutex()

static thread_safe_func()
{
  lock.Lock()
  static const Class::NonThreadSafeClassName() *array[16] = {
    Class::NonThreadSafeClassName(),
    Class::NonThreadSafeClassName(),
    Class::NonThreadSafeClassName(),
    Class::NonThreadSafeClassName(),
    Class::NonThreadSafeClassName(),
    Class::NonThreadSafeClassName(),
    Class::NonThreadSafeClassName(),
  }
  lock.Unlock()
  ... code continues here
}

стоит и гарантирует, что этот код теперь потокобезопасен?

1 Ответ

5 голосов
/ 05 марта 2012

Под C ++ 03 , ни ...

void foo() {
  static your_variable = ...;
}

... ни ...

void foo() {
    lock.Lock();
    static your_variable = ...;
    lock.Unlock();
}

... потокобезопасны.

Первый не является потокобезопасным, поскольку стандарт ничего не говорит о том, что второй поток входит в функцию, пока первый поток все еще выполняет инициализацию. На самом деле, стандарт вообще не имеет понятия о потоках.

Второй не является потокобезопасным, поскольку инициализация происходит, когда поток выполнения входит в функцию (в первый раз), что на до lock.Lock().


В C ++ 11 , инициализация локальной статической переменной является поточно-ориентированной .

...