如果中间有线程连接,为什么不能使用宽松的原子操作来同步内存?
Why can't you use relaxed atomic operations to synchronize memory, if there is a thread join in between?
我正在看 Herb Sutter 的演讲:https://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2
看两个例子(大约 1:15 标记),一个对我有意义,另一个对我来说没有意义。
第一个例子(有道理):
注意 count
是一个原子整数。
在这里,对 load/store 计数使用宽松的内存排序据说是可以的,因为线程退出发生在从线程上的连接返回之前。这意味着松弛添加发生在松弛加载之前。
子线程:
while (...) {
if (...) {
count.fetch_add(1, memory_order_relaxed);
}
}
主线程:
int main() {
launch_workers();
join_workers();
cout << count.load(memory_order_relaxed);
}
第二个例子(不清楚):
注意 dirty
和 stop
是原子布尔值。
这里讲的是dirty
上的store和load必须分别使用release和acquire排序,因为dirty
是用来发布一些数据,这些数据是为了清理而读取的。
子线程:
while(!stop.load(memory_order_relaxed)) {
if (...) {
// publish some data
dirty.store(true, memory_order_release)
}
}
主线程:
int main() {
launch_workers();
stop = true;
join_workers();
if (dirty.load(memory_order_acquire)) {
// read published data to clean up
}
}
我的问题是,在第二个示例中,为什么不能在线程退出和从线程的连接返回之间应用相同的 'happens before' 关系来同步内存?
我认为它可以在 dirty
的操作上使用宽松的内存排序的方式是:
[子线程做一些工作,包括发布数据]
[子线程退出]-(发生在之前)->[Return从子线程加入join_workers()
调用]
[主线程都将 dirty
视为 true 并且可以安全地读取已发布的数据以进行清理]
在 1:17:25 附近,他说“现在,因为你碰巧知道我通过加入线程获得了 release-acquire,所以我在其中注入了 release-acquire;这可能已经足够好了,你可以去放松一下”。所以他似乎在说,最后,如果 dirty
以宽松的内存顺序访问实际上没问题。
我正在看 Herb Sutter 的演讲:https://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2
看两个例子(大约 1:15 标记),一个对我有意义,另一个对我来说没有意义。
第一个例子(有道理):
注意 count
是一个原子整数。
在这里,对 load/store 计数使用宽松的内存排序据说是可以的,因为线程退出发生在从线程上的连接返回之前。这意味着松弛添加发生在松弛加载之前。
子线程:
while (...) {
if (...) {
count.fetch_add(1, memory_order_relaxed);
}
}
主线程:
int main() {
launch_workers();
join_workers();
cout << count.load(memory_order_relaxed);
}
第二个例子(不清楚):
注意 dirty
和 stop
是原子布尔值。
这里讲的是dirty
上的store和load必须分别使用release和acquire排序,因为dirty
是用来发布一些数据,这些数据是为了清理而读取的。
子线程:
while(!stop.load(memory_order_relaxed)) {
if (...) {
// publish some data
dirty.store(true, memory_order_release)
}
}
主线程:
int main() {
launch_workers();
stop = true;
join_workers();
if (dirty.load(memory_order_acquire)) {
// read published data to clean up
}
}
我的问题是,在第二个示例中,为什么不能在线程退出和从线程的连接返回之间应用相同的 'happens before' 关系来同步内存?
我认为它可以在 dirty
的操作上使用宽松的内存排序的方式是:
[子线程做一些工作,包括发布数据]
[子线程退出]-(发生在之前)->[Return从子线程加入join_workers()
调用]
[主线程都将 dirty
视为 true 并且可以安全地读取已发布的数据以进行清理]
在 1:17:25 附近,他说“现在,因为你碰巧知道我通过加入线程获得了 release-acquire,所以我在其中注入了 release-acquire;这可能已经足够好了,你可以去放松一下”。所以他似乎在说,最后,如果 dirty
以宽松的内存顺序访问实际上没问题。