gpt4 book ai didi

java - VarHandle 获取/设置不透明

转载 作者:搜寻专家 更新时间:2023-11-01 02:18:59 32 4
gpt4 key购买 nike

我一直在努力理解 VarHandle::setOpaqueVarHandle::getOpaque 真正在做什么。到目前为止,这并不容易 - 我认为有些东西我得到了(但不会在问题本身中提出它们,以免混淆水域),但总的来说,这充其量是误导对我来说。

文档:

Returns the value of a variable, accessed in program order...

在我的理解中,如果我有:

int xx = x; // read x
int yy = y; // read y

这些读取可以重新排序。另一方面,如果我有:

// simplified code, does not compile, but reads happen on the same "this" for example
int xx = VarHandle_X.getOpaque(x);
int yy = VarHandle_Y.getOpaque(y);

这次不能重新订货了?这就是“程序顺序”的意思?我们是在谈论在这里插入障碍以禁止这种重新排序吗?如果是这样,因为这是两个负载,是否可以实现相同的目标?通过:

 int xx = x;
VarHandle.loadLoadFence()
int yy = y;

但它变得更加棘手:

... but with no assurance of memory ordering effects with respect to other threads.

我无法想出一个例子来假装我理解这部分内容。

在我看来,这份文档是针对那些确切知道自己在做什么的人(而我绝对不是这样的人)......所以有人可以在这里阐明一些问题吗?

最佳答案

Well in my understanding if I have:

int xx = x; // read x
int yy = y; // read y

These reads can be re-ordered.

这些读取可能不仅碰巧被重新排序,它们可能根本不会发生。线程可能使用旧的、以前读取的 x 和/或 y 的值,或者它以前写入这些变量的值,而实际上,写入可能不是尚未执行,因此“读取线程”可能会使用值,其他线程可能不知道并且当时不在堆内存中(并且可能永远不会)。

On the other had if I have:

// simplified code, does not compile, but reads happen on the same "this" for example
int xx = VarHandle_X.getOpaque(x);
int yy = VarHandle_Y.getOpaque(y);

This time re-orderings are not possible? And this is what it means "program order"?

简单地说,不透明读写的主要特征是,它们会实际发生。这意味着它们不能相对于至少具有相同强度的其他内存访问重新排序,但这对普通读取和写入没有影响。

术语 program order由 JLS 定义:

… the program order of t is a total order that reflects the order in which these actions would be performed according to the intra-thread semantics of t.

那是 evaluation order指定用于表达式和语句。我们感知效果的顺序,只要只涉及一个线程。

Are we talking about insertions of barriers here for this re-ordering to be prohibited?

不,不涉及障碍,这可能是短语“……但不保证相对于其他线程的内存排序效果”背后的意图。

也许,我们可以说不透明访问的工作方式有点像 Java 5 之前的 volatile,强制读取访问以查看最新的堆内存值(只有在写入端也使用不透明或更强的模式),但对其他读取或写入没有影响。

那么你能用它做什么?

一个典型的用例是取消或中断标志,它不应建立发生在 关系。通常,已停止的后台任务没有兴趣感知停止任务在发出信号之前所做的操作,而只会结束自己的 Activity 。因此,使用不透明模式写入和读取标志足以确保最终注意到信号(与正常访问模式不同),但不会对性能产生任何额外的负面影响。

同样,后台任务可以写入进度更新,如百分比数字,报告 (UI) 线程应该及时注意到,而在发布之前不需要happens-before关系最终结果。

如果您只想对 longdouble 进行原子访问,而没有任何其他影响,它也很有用。

由于使用 final 字段的真正不可变对象(immutable对象)不受数据竞争的影响,您可以使用不透明模式及时发布不可变对象(immutable对象),而不会产生发布/获取模式发布的更广泛影响。

一种特殊情况是定期检查预期值更新的状态,一旦可用,就以更强的模式查询值(或显式执行匹配的围栏指令)。原则上,happens-before 关系只能在写入和后续读取之间建立,但由于优化器通常没有识别此类线程间用例的范围,因此性能至关重要代码可以使用不透明访问来优化这种情况。

关于java - VarHandle 获取/设置不透明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56342141/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com