比方说,我有两个线程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#include #include #include #include using namespace std; mutex mA, mB, coutMutex; bool fA = false, fB = false; int main() { thread A{ []{ lock_guard lock{mA}; fA = true; } }; thread B{ [] { lock_guard 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 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 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
使用顺序一致的内存顺序或获取/释放内存顺序使用变量来实现自旋锁.所以问题是一个std::mutex
行为就像一个顺序一致的自旋锁或一个获取/释放内存顺序自旋锁.
是的,这是允许的,因此:不,std::mutex
不一定是顺序一致的.
std::mutex
标准中没有定义为顺序一致,只有那样
30.4.1.2互斥体类型[thread.mutex.requirements.mutex]
11同步:对同一对象的先前解锁()操作应与(1.10)此操作[lock()]同步.
Synchronize-with似乎定义在同一个std::memory_order::release/acquire
(见这个问题).
据我所知,获取/释放自旋锁将满足std :: mutex的标准.