我正在阅读Anthony Williams的C++ Concurrency in Action。目前我在他消耗memory_order_consume的时候。
在该块之后有:
现在我已经介绍了内存排序的基础知识,现在是时候看一下了 更复杂的部分
这让我有点害怕,因为我不完全理解几件事:
依赖于ordered-ordered-before如何与synchronize-with不同?他们都创造了以前的关系。有什么区别?
我对以下示例感到困惑:
int global_data[]={ … };
std::atomic<int> index;
void f()
{
int i=index.load(std::memory_order_consume);
do_something_with(global_data[std::kill_dependency(i)]);
}
kill_dependency到底做了什么?它杀死了哪种依赖?哪个实体之间?编译器如何利用这种知识?
是否可以使用memory_order_acquire安全地替换memory_order_consume的所有事件?即在各方面都更严格吗?
在代码清单5.9中,我可以安全地替换
std::atomic<int> data[5]; // all accesses are relaxed
与
int data[5]
?即可以获取和释放用于同步对非原子数据的访问吗?
他描述了放松,获得并通过一些例子释放了小屋中的男人。是否有一些类似的简单描述seq_cst并消耗?
答案 0 :(得分:5)
关于下一个问题,答案需要更多解释。当多个线程访问相同的数据时,有三件事可能会出错:
系统可能会在读取或写入过程中切换线程,产生的结果是一半的值和另一半的值。
编译器可能会移动代码,假设没有其他线程查看所涉及的数据。
处理器可能在其本地缓存中保留一个值,而在更改值后不更新主内存或在另一个线程更改主内存中的值后重新读取它。
内存顺序地址仅数字3.原子函数地址1和2,并且,根据内存顺序参数,也可能是3。所以memory_order_relaxed意味着“不要打扰3号。代码仍然处理1和2.在这种情况下,你将使用获取和释放来确保正确的内存排序。
答案 1 :(得分:3)
dependency-ordered-before如何与synchronize-with不同?
从1.10 / 10开始:“[注意:关系”是依赖性排序之前“类似于”与“同步”,但使用释放/消费代替释放/获取。 - 结束注释]“。
kill_dependency到底做了什么?
一些编译器进行数据依赖性分析。也就是说,它们跟踪变量中值的变化,以便更好地确定必须同步的内容。 kill_dependency
告诉这些编译器不要再跟踪,因为编译器无法理解代码中发生的事情。
可以安全地替换memory_order_consume的所有事件 memory_order_acquire?即在各方面都更严格吗?
我是这么认为的,但我不确定。
答案 2 :(得分:2)
memory_order_consume要求原子操作发生在所有依赖于它的数据的非原子操作之前。数据依赖性是指在不使用该数据的情况下无法计算表达式的任何依赖关系。例如,在x-> y中,没有先评估x,就无法评估x-> y。
kill_dependency是一个独特的功能。所有其他函数都对其参数具有数据依赖性。 Kill_dependency明确没有。当您知道数据本身已经同步时,它会显示,但是您可能无法同步获取数据所需的表达式。在您的示例中,允许do_something_with假设globalldata [i]的任何缓存值都是安全的,但我本身必须是正确的原子值。
memory_order_acquire严格更强如果所有对数据的更改都使用匹配的memory_order_release正确发布。