同一互斥锁顺序上的锁定和解锁是否一致?
Are lock and unlock on the same mutex sequential consistent?
对于互斥lock()
,标准提到:
同一互斥锁上的先前 unlock(( 操作与此操作同步(如 std::memory_order 中定义(。
这个答案试图根据标准解释synchronize-with
的含义。但是,看起来定义没有明确指定。
我的主要问题是,我能得到这个输出吗:
x: 1
y: 2
由于线程 A 中的内存重新排序,以下代码?如果B
在A
解锁后锁定,是否保证A
x
中的写入被B
观察到?
std::mutex mutex;
int x = 0, y = 0;
int main() {
std::thread A{[] {
x = 1;
std::lock_guard<std::mutex> lg(std::mutex);
y = 0;
}};
std::thread B{[] {
std::lock_guard<std::mutex> lg(std::mutex);
y = x + 2;
}};
A.join();
B.join();
std::cout << "x: " << x << std::endl;
std::cout << "y: " << y << std::endl;
}
如果没有,基于标准的哪个部分? 换句话说,我们可以假设锁定/解锁之间存在顺序一致性吗?
我也看到了这个相关的问题,但它是针对单独的互斥体的。
与同步关系已明确定义。该标准规定如下:
某些库调用与另一个线程执行的其他库调用同步。例如,原子存储发布与从存储中获取其值的加载获取同步。[...][注意:同步操作的规范定义一个操作何时读取另一个操作写入的值。对于原子对象,定义是明确的。给定互斥锁上的所有操作都发生在一个总订单中。每次互斥锁获取都会"读取"上一个互斥锁版本写入的值。— 尾注]
并进一步:
对原子对象 M 执行释放操作的原子操作A与对M执行获取操作并从释放中的任何副作用中获取其值的原子操作B同步 以A为首的序列。
换句话说,如果获取操作 A "看到">发布操作 B 存储的值,则A与B同步。
考虑一个自旋锁,你只需要一个原子布尔标志。所有操作都在该标志上运行。为了获取锁,您已经使用原子读取-修改-写入操作设置了标志。对原子对象的所有修改都完全按修改顺序排序,并且可以保证 RMW 操作始终读取与该 RMW 操作关联的写入之前写入的最后一个值(按修改顺序(。
由于这种保证,对锁定/解锁操作使用获取/释放语义就足够了,因为成功的锁定操作始终"看到"上一个解锁写入的值。
关于您的问题:
如果
B
在A
解锁后锁定,B
是否保证遵守x
A
写入?
重要的部分是"如果B
解锁后A
锁定"!如果这是有保证的,那么是的,B
的锁定操作与A
的解锁同步,从而建立发生之前的关系。因此B
将观察A
的写作。但是,您的代码不能保证B
在A
后锁定,因此您有一个潜在的数据争用,这将导致@ReinstateMonica正确指出的未定义行为。
更新
对 x 的写入是在A
解锁之前排序的。操作是否在互斥锁之外(之前(并不重要。事实上,从理论上讲,编译器可以对操作进行重新排序,使其最终进入互斥锁(尽管这不太可能(。之前排序也是发生前定义的一部分,因此我们有以下内容:
std::thread A{[] {
x = 1; // a
std::lock_guard<std::mutex> lg(std::mutex);
y = 0;
// implicit unlock: b
}};
std::thread B{[] {
std::lock_guard<std::mutex> lg(std::mutex); // c
y = x + 2;
}};
假设B
在A
解锁后锁定,我们有:
- 排序 ->A发生在B之前 b
- 与 c 同步 ->b发生在c之前
由于发生前关系是传递的,因此在c之前发生。所以是的,对于在A
解锁之前排序的所有操作都是如此 - 无论它们是否在锁内。
- 我应该在锁定TBitmap画布后解锁它吗
- 虚假唤醒是否会解锁所有等待线程,甚至是不相关的线程?
- 同一互斥锁顺序上的锁定和解锁是否一致?
- c++ 为什么我不应该从不同的线程解锁互斥锁
- 在新作用域中使用unique_lock是否等效于在使用共享资源的工作结束时解锁调用
- 锁定的互斥锁是否保护condition_variable和数据?
- 在代码的其他部分中对lock_gard和不使用相同的互斥锁是否安全?
- "data race"(不是真的)在通知条件变量并解锁关联的互斥锁后
- 程序输入密码并解锁窗口7,8,10
- 在通知之前完成手动解锁
- 当在其他地方使用相同的互斥锁时,等待/通知unique_lock互斥锁是否安全lock_guard
- STD :: Mutex如何在不同的线程中解锁
- C++:带有"std::lock_guard"的互斥锁是否足以同步两个"std::thre
- 如何使用单个解锁方法(可称为读取器或写入器)实现C++读写器锁?
- 如何在C 中自动汇总日志消息并自动解锁互斥X
- mutex::lock() 检查一次解锁状态是否已经被另一个线程锁定?
- 释放锁定的内存是否会解锁相应的页面
- VirtualFree是否解锁VirtualLock ?
- 如果unique_lock在其生命周期内不会再次使用,是否应该在解锁后释放?
- pthread_cond_signal函数是否解锁调用线程锁定的互斥对象