Я думаю, что причина, по которой цитата cppreference о мьютексах написана таким образом, заключается в том, что если вы используете мьютексы для синхронизации, все общие переменные, используемые для связи, всегда должны быть доступны внутри критической секции.
Стандарт 2017 года говорит в 4.7.1:
вызов, который получает мьютекс, будет выполнять операцию получения в местоположениях, включающих мьютекс.Соответственно, вызов, который освобождает тот же мьютекс, будет выполнять операцию освобождения в тех же местах.Неформально выполнение операции освобождения A приводит к тому, что предшествующие побочные эффекты в других областях памяти становятся видимыми для других потоков, которые впоследствии выполняют операцию потребления или получения для A.
Обновление: Я хочу убедиться, что у меня есть солидный пост, потому что на удивление трудно найти эту информацию в Интернете.Спасибо @Davis Herring за указание на правильное направление.
Стандарт гласит:
в 33.4.3.2.11 и 33.4.3.2.25 :
разблокировка мьютекса синхронизируется с последующими операциями блокировки, которые получают владение тем же объектом
(https://en.cppreference.com/w/cpp/thread/mutex/lock, https://en.cppreference.com/w/cpp/thread/mutex/unlock)
в 4.6.16 :
Каждое вычисление значения и побочный эффект, связанный с полным выражением, секвенируется перед каждым значениемвычисление и побочный эффект, связанный со следующим полным выражением, которое будет оценено.
https://en.cppreference.com/w/cpp/language/eval_order
in 4.7.1.9 :
Оценка A между потоками происходит до оценки B, если
4.7.1.9.1) - A синхронизируется с B, или
4.7.1.9.2) - A упорядочен по зависимости перед B, или
4.7.1.9.3) - для некоторой оценки X
4.7.1.9.3.1) ------A синхронизируется с X, а последовательность X перед B или
4.7.1.9.3.2) ------ A секвенируется до того, как X и X-поток происходит до B, или
4.7.1.9.3.3) ------ A inter-поток происходит до того, как X и X-потоки происходят до B.
https://en.cppreference.com/w/cpp/atomic/memory_order
- Таким образом, разблокировка мьютекса B inter-thread происходит до последующая блокировка C на 4.7.1.9.1.
- Любая оценка A, которая происходит в программном порядке до разблокировки мьютекса B, также inter-thread происходит до C на 4.7.1.9.3.2
- Поэтому после
unlock()
гарантирует, что все предыдущие записи, даже те, которые находятся вне критической секции, должны быть видимы для совпадающего lock()
.
Этот вывод согласуется скак мьютексы реализованы сегодня (и были в прошлом), так что все программный порядок предыдущих загрузок и хранилищ завершаются перед разблокировкой.(Точнее, магазины должны быть видны до того, как будет видна разблокировка, когда наблюдается соответствующая операция блокировки в любом потоке.) Нет сомнений, что это является общепринятым определением выпуска в теории и на практике.