Страницы

Поиск по вопросам

пятница, 26 апреля 2019 г.

Блокировка с двойной проверкой

В книге Энтони Уильямса "Параллельное программирование на C++ в действии" рекомендуется заменять использование упомянутого в заголовке паттерна использованием std::call_once. Немного погуглив, обнаружил, что в других языках, например, Java и C# подобная проблема решается объявление переменной как volatile для предотвращение оптимизаций компилятором. Является ли использование volatileрешением и в C++ ? Или же здесь она работает как-то иначе?


Ответ

нет, не является. Дело в том, что даже в этом случае можно сделать "обход". Детально расписано на хабре
Суть в том, что мы думаем, что в коде, одна строка атомарна, а это далеко не так.
template T& single() { static T* pt; if (pt == 0) // первая проверка, вне мьютекса { StaticLock lock; if (pt == 0) // вторая проверка, под мьютексом pt = new T; // вот здесь на самом деле две строки. } return *pt; }
создание объекта это обычно две операции - собственно выделение память и вызов конструктора. И в этом случае может так оказаться, что память уже выделили, а по адресу ещё не создали объект. И самая первая проверка теперь отработает по другому.

Комментариев нет:

Отправить комментарий