与原子内存围栏同步C++
Synchronization with C++ atomic memory fence
我有一个关于使用内存围栏同步以下代码的问题。
std::atomic<int> a = 0;
std::atomic<int> b = 0;
void increase_b() {
std::atomic_thread_fence(std::memory_order_release);
b.store(1, std::memory_ordered_relaxed);
}
bool diff() {
int val_a = a.load(std::memory_ordered_relaxed);
int val_b = b.load(std::memory_ordered_relaxed);
return val_b > val_a;
}
void f1() {
increase_b();
std::atomic_thread_fence(std::memory_order_seq_cst);
}
void f2() {
std::atomic_thread_fence(std::memory_order_seq_cst);
bool result = diff();
}
int main() {
std::thread t1(f1);
std::thread t2(f2);
t1.join(); t2.join();
}
假设 t1 已经完成了f1
,然后 t2 刚刚开始f2
,将 t2 请参阅b
递增?
你的代码过于复杂。a=0
永远不会更改,因此它始终显示为 0。 您不妨只atomic<int> b=0;
并且只有一个只返回b.load
的负载。
完成了 f1,然后 t2 刚刚开始 f2,t2 会看到 b 递增吗?
你没有办法检测到这就是时间安排的方式,除非你把t1.join()
放在std::thread t2(f2);
施工之前。 这将要求线程 2 中的所有内容在线程 1 中的所有内容之后排序。 (我认为即使在 f1 结束时没有seq_cst
围栏,但这并没有什么坏处。 我认为thread.join确保线程内完成的所有操作在thread.join
之后都是可见的(
但是,是的,这种排序可能是偶然发生的,然后它当然有效。
从C++方面来说,这甚至不能保证是一个有意义的条件。
但可以肯定的是,对于大多数(所有?(实际实现来说,这是可能发生的。thread_fence(mo_seq_cst)
将编译为一个完整的屏障,该屏障阻止该线程,直到存储提交(对所有线程全局可见(。 因此,在从其他线程读取可以看到b
的更新值之前,执行不能离开 f1。 (C++标准根据创建同步关系来定义排序和栅栏,而不是编译为刷新存储缓冲区的完整屏障。 该标准没有提到存储缓冲区或 StoreLoad 重新排序或任何 CPU 内存排序的东西。
给定合成条件,线程实际上是相互排序的,它的工作原理就像一切都在单个线程中完成一样。
diff()
中的负载不是相互排序的,因为它们都是mo_relaxed
的。 但是a
永远不会被任何线程修改,所以唯一的问题是b.load()
是否可以在线程开始之前,在f1
存储可见之前发生。 在实际实现中,它不能,因为">然后t2刚刚启动f2"是什么意思。如果它可以加载旧值,那么你就不能说">然后",所以它几乎是一个重言式。
加载前的thread_fence(seq_cst)
并没有真正帮助任何东西。 我想它会阻止b.load()
使用线程启动机制重新排序。
- 松弛原子与无同步情况下的记忆连贯性
- 使用QQuickFramebufferObject时同步数据的最佳方式是什么
- 在C++中同步线程
- 与 stdio 同步是否使程序 I/O 非交互式?
- 如何在qt中同步应用程序和显示器的刷新率?
- Windows 进程间同步类似事件?
- 当对套接字 send() 的同步调用由于连接另一端丢失而被阻止时,如何恢复?
- 将 10 个线程与原子布尔值同步
- ofstream::close() 是否在 Linux 上调用同步?
- 与Visual Studios(c ++)同步时如何组织github存储库?
- 原子获取是否与互斥锁释放同步?
- Boost (Beast) websocket:同步写入挂起
- Postgres vs MySQL:命令不同步;.
- 线程过程中的线程同步问题
- 同步读取多个 TCP 响应
- 同步两个具有不同帧速率的传感器
- 如何定期同步线程?
- 同步对多个向量进行排序
- 同步类中的公共变量
- 如何检查 ntpd 是否仍在运行和同步