Дважды проверил шаблон блокировки в C ++ 11? - PullRequest
11 голосов
/ 15 мая 2011

Новая модель машины C ++ 11 позволяет надежно работать многопроцессорным системам.к реорганизации инструкций.

Как Мейерс и Александреску указали на "простой" шаблон двойной блокировки с проверкой Реализация не безопасна в C ++ 03

Singleton* Singleton::instance() {
  if (pInstance == 0) { // 1st test
    Lock lock;
    if (pInstance == 0) { // 2nd test
      pInstance = new Singleton;
    }
  }
  return pInstance;
}

Они показали в своей статье , что независимо от того, что вы делаете как программист, в C ++ 03 у компилятора слишком много свободы: разрешается переупорядочивать инструкции таким образом, чтобыВы можете не быть уверенным, что у вас останется только один экземпляр Singleton.

Мой вопрос сейчас:

  • Есть ограничения / определенияновая машинная модель C ++ 11 теперь ограничивает последовательность инструкций, что приведенный выше код всегда будет работать с компилятором C ++ 11?
  • Как безопасная реализация C ++ 11 этого шаблона Singletonтеперь выглядит, когда используются новые библиотечные средства (вместо макета Lock здесь)?

Ответы [ 3 ]

5 голосов
/ 15 мая 2011

Если pInstance является обычным указателем, код имеет потенциальную гонку данных - операции над указателями (или любым встроенным типом, в этом отношении) не гарантированно будут атомарными (РЕДАКТИРОВАТЬ: или хорошо упорядочены )

Если pInstance является std::atomic<Singleton*> и Lock внутренне использует std::mutex для достижения синхронизации (например, если Lock на самом деле std::lock_guard<std::mutex>), код должен быть гонки данных бесплатно.

Обратите внимание, что для правильной синхронизации вам необходимо и явная блокировка, и атомарный pInstance.

4 голосов
/ 05 сентября 2013

Поскольку инициализация статической переменной теперь гарантированно безопасна для потоков, синглтон Мейера должен быть безопасным для потоков.

Singleton* Singleton::instance() {
  static Singleton _instance;
  return &_instance;
}

Теперь вам нужно решить главную проблему: в вашем коде есть синглтон.

РЕДАКТИРОВАТЬ: на основе моего комментария ниже: Эта реализация имеет большой недостаток по сравнению с другими. Что произойдет, если компилятор не поддерживает эту функцию? Компилятор будет выдавать поток небезопасного кода даже без выдачи предупреждения. Другие решения с блокировками не будут компилироваться, даже если компилятор не поддерживает новые интерфейсы. Это может быть хорошей причиной, чтобы не полагаться на эту функцию, даже для вещей, отличных от одиночных.

1 голос
/ 15 мая 2011

C ++ 11 не меняет смысла этой реализации двойной проверки блокировки. Если вы хотите, чтобы блокировка с двойной проверкой работала, вам необходимо установить подходящие барьеры / ограждения памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...