Является ли std :: mutex последовательно последовательным?

Скажи у меня две темы A а также B запись в глобальные логические переменные fA а также fB соответственно которые изначально установлены на false и защищены std::mutex объекты mA а также mB соответственно:

// Thread A
mA.lock();
assert( fA == false );
fA = true;
mA.unlock();

// Thread B
mB.lock()
assert( fB == false );
fB = true;
mB.unlock()

Можно ли наблюдать за изменениями на fA а также fB в разных порядках в разных темах C а также D? Другими словами, может ли следующая программа

#include <atomic>
#include <cassert>
#include <iostream>
#include <mutex>
#include <thread>
using namespace std;

mutex mA, mB, coutMutex;
bool fA = false, fB = false;

int main()
{
thread A{ []{
lock_guard<mutex> lock{mA};
fA = true;
} };
thread B{ [] {
lock_guard<mutex> lock{mB};
fB = true;
} };
thread C{ [] { // reads fA, then fB
mA.lock();
const auto _1 = fA;
mA.unlock();
mB.lock();
const auto _2 = fB;
mB.unlock();
lock_guard<mutex> lock{coutMutex};
cout << "Thread C: fA = " << _1 << ", fB = " << _2 << endl;
} };
thread D{ [] { // reads fB, then fA (i. e. vice versa)
mB.lock();
const auto _3 = fB;
mB.unlock();
mA.lock();
const auto _4 = fA;
mA.unlock();
lock_guard<mutex> lock{coutMutex};
cout << "Thread D: fA = " << _4 << ", fB = " << _3 << endl;
} };
A.join(); B.join(); C.join(); D.join();
}

легальная печать

Thread C: fA = 1, fB = 0
Thread D: fA = 0, fB = 1

в соответствии со стандартом C ++?

Замечания: Спин-блокировка может быть реализована с помощью std::atomic<bool> переменные, использующие либо последовательный последовательный порядок памяти, либо порядок получения / освобождения памяти. Так что вопрос в том, std::mutex ведет себя как последовательно согласованная спин-блокировка или спин-блокировка порядка получения / освобождения памяти.

9

Решение

Да, это разрешено, поэтому: нет, std::mutex не обязательно последовательно последовательно.

std::mutex не определено в стандарте, чтобы быть последовательно последовательным, только то, что

30.4.1.2 Типы мьютекса [thread.mutex.requirements.mutex]

11 Синхронизация: до операции unlock () над одним и тем же объектом
синхронизировать с (1.10) эту операцию [замок()].

Синхронизировать-с кажется, определен в том же был std::memory_order::release/acquire (увидеть этот вопрос).
Насколько я вижу, спин-блокировка получения / выпуска будет соответствовать стандартам для std :: mutex.

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]