我有一个非原子变量my_var
和一个std::mutex my_mut
。我假设到目前为止,程序员已经遵循了以下规则:
每次程序员修改或写入
my_var
时,他都会锁定并解锁my_mut
假设这样,Thread1
执行以下操作:
my_mut.lock();
my_var.modify();
my_mut.unlock();
这是我在脑海中想象的事件顺序:
前- 对于
my_mut.lock();
,在主存和一些本地缓存中可能存在my_var
的多个副本。即使程序员遵循了规则,这些值也不一定一致。 - 通过
my_mut.lock();
指令,之前执行的my_mut
临界区的所有写操作在内存中对该线程都是可见的。 my_var.modify();
执行。 >
my_mut.unlock();
,在主存和一些本地缓存中可能有my_var
的多个副本。即使程序员遵循了规则,这些值也不一定一致。在这个线程结束时,my_var
的值对于下一个锁定my_mut
的线程来说是可见的,当它锁定my_mut
的时候。我一直有麻烦找到一个来源,验证这正是std::mutex
应该如何工作。我参考了c++标准。从ISO 2013中,我发现了这个部分:
[注:例如,一个获取互斥锁的调用将执行一个对组成互斥锁的位置进行获取操作。相应地,释放同一个互斥锁的调用将执行a在同一地点进行释放行动。非正式地,执行对A的释放操作会对其他内存产生先前的副作用的其他线程可以看到的位置a上的消费或获取操作
我对std::mutex
的理解是否正确?
c++处理的是操作之间的关系,而不是某些特定的硬件术语(比如缓存内聚)。所以c++标准有一个在之前发生的关系,这大致意味着在之前发生的任何完成了它的所有副作用,因此在之后发生的那一刻是可见的。
如果你已经进入了一个独占的临界会话,这意味着无论在其中发生什么,都会在下次进入该临界区之前发生。所以任何相应的人都会看到之前发生的一切。这就是标准所要求的。其他一切(包括缓存内聚)都是实现的责任:它必须确保所描述的行为与实际发生的一致。