繁体   English   中英

如何理解JDK9 memory model?

[英]How to understand JDK9 memory model?

我正在学习 JDK9 memory model。

After watching the speech Java Memory Model Unlearning Experience and reading the paper Using JDK 9 Memory Order Modes .

我对一些概念感到困惑。

  1. opaque是否立即保证可见性

  2. 如何理解论文中的偏序全序

对于第一个问题,论文说

使用裸旋转等待变量值几乎从来都不是一个好主意。 使用 Thread.onSpinWait、Thread.yield 和/或阻塞同步来更好地应对“最终”可能需要很长时间这一事实,尤其是当系统上的线程数多于内核数时。

所以如果我写代码:

// shared variable I and VarHandle I_HANDLE which referred to I
public static int I = 0;

public static final VarHandle I_HANDLE;

// Thread-1
I_HANDLE.setOpaque(1);

// Thread-2
while((int) I_HANDLE.getOpaque() == 0){
}

线程 2 最终会终止,但可能会在很长一段时间后终止?

如果是这样,是否有任何最小的方法来保证线程 2 立即看到线程 1 的修改? (发布/获取?易失性?)

没有像“立即”这样的更新。 甚至电也以有限的速度运动。 一般来说,在特定时间跨度内要求可感知的效果就像要求操作的特定执行时间一样。 两者都不能保证,因为它们是 JVM 无法更改的基础架构的属性。

实际上,当然,JVM 开发人员试图使操作尽可能快,作为程序员,对您来说最重要的是,对于更新的线程间可见性,没有比不透明写入更快的替代方案。 更强的访问模式不会改变更新变得可见的速度,它们会为读取和写入的重新排序添加额外的约束。

因此,在您的示例中,只要架构和系统负载允许1 ,更新就会变得可见,但不要询问实际数字。 没有人能说这需要多长时间。 如果您需要时间数量方面的保证,您需要一个特殊的(“实时”)实现,它可以为您提供除 Java Memory ZA559B87068921EEC05086CE5485E9748 之外的额外保证


1举一个实际场景:线程 1 和 2 可能竞争同一个 CPU。 线程 1 写入值并在任务切换之前继续运行操作系统特定时间(甚至不能保证线程 2 是下一个)。 这意味着写入后可能会经过相当长的时间,无论是挂钟时间还是线程 1 的进度。 当然,其他线程也可能同时在其他 CPU 内核上取得很大进展。 但也有可能线程 2 在线程 1 提交写入之前轮询是线程 1 没有机会写入新值的原因。 这就是为什么您应该使用onSpinWaityield标记此类轮询循环,以使执行环境有机会防止此类情况发生。 有关两者之间差异的讨论,请参阅此问答

简单来说,不透明意味着读取或写入将要发生。 所以它没有被编译器优化掉。

它不提供关于其他变量的任何排序保证。

因此,它适用于性能计数器,其中 1 个线程进行更新,其他线程读取它。

但是,如果您要执行以下操作(伪)

// global
final IntReference a = new IntReference();
final IntReference b = new IntReference();

void thread1(){
    a.setPlain(1);
    b.setOpaque(1);
}

void thread2(){
    int r1 = b.getOpaque();
    int r2 = a.getPlain();
    if(r1 == 1 && r2 == 0) println("violation");
}

然后可能是“违规”被打印出来,因为:

  • a,b 的商店重新排序
  • 来自 a 和 b 的负载被重新排序。

但是,如果您使用存储发布和加载获取,则不会发生重新排序,因为发布和获取提供了相对于其他变量的排序约束。

void thread1(){
    a.setPlain(1);
    [StoreStore] <--
    [LoadStore]
    b.setRelease(1);
}

void thread2(){
    int r1 = b.getAcquire();
    [LoadLoad] <---
    [LoadStore]
    int r2 = a.getPlain();
    if(r1 == 1 && r2 == 0) println("violation");
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM