微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Java同步的内存影响

如何解决Java同步的内存影响

简而言之,就是 。这不是一个严重的问题,因为JSR-133是非规范性文档,不属于语言或JVM标准。而是,只有文档解释了一种可能的策略,该策略 足以 实现内存模型,但通常不是 必需的 。最重要的是,有关“缓存刷新”的评论基本上完全不合时宜,因为实质上零的体系结构可以通过执行任何类型的“缓存刷新”来实现Java内存模型(许多体系甚至没有这样的指令)。

Java内存模型是根据可见性,原子性,发生关系之前的事物等形式正式定义的,它使用精确(数学上)定义的方法,确切地解释了哪些线程 必须 看到什么,在其他操作和其他关系之前 必须 执行哪些操作。模型。未正式定义的行为可能是随机的,也可能是在某些硬件和JVM实现上的实践中明确定义的行为- 但是您当然不应该依赖它,因为将来它可能会发生变化,并且您永远无法真正确定除非您编写了JVM并且对硬件语义了如指掌,否则首先要对它进行明确定义。

因此,您引用的文本不是正式描述Java保证的内容,而是描述某种具有非常弱的内存顺序和可见性保证的假设体系结构如何使用缓存刷新 满足Java内存模型要求。显然,关于缓存刷新,主内存等的任何实际讨论通常都不适用于Java,因为这些概念在抽象语言和内存模型规范中不存在。

在实践中,内存模型提供的保证要比完全刷新弱得多- 每次原子,并发相关或锁定操作刷新整个高速缓存都将是非常昂贵的,并且在实践中几乎从未做到过。而是使用特殊的原子cpu操作,有时与内存屏障指令结合使用,这有助于确保内存可见性和顺序。因此,通过注意到第一个为true而第二个为非,廉价的无竞争的同步与“完全刷新缓存”之间的明显不一致得到了解决- Java内存模型不需要完全刷新(实际上没有刷新发生)。

如果正式记忆模型过于繁琐而无法消化(您不会孤单),您还可以通过阅读Doug Lea的菜谱深入研究该主题,该菜谱实际上与JSR-133常见问题解答相关,但这是从具体的硬件角度出发的问题,因为它是针对编译器作者的。在这里,他们确切地讨论了特定操作(包括同步)所需的障碍,并且在那里讨论的障碍可以很容易地映射到实际硬件。食谱中讨论了许多实际映射。

解决方法

JSR-133常见问题解答说:

但是同步不仅仅是相互排斥。同步确保以可预见的方式使线程在同步块之前或期间对内存的写入对于在同一监视器上同步的其他线程可见。退出同步块后,我们释放监视器,其作用是将缓存刷新到主内存,以便该线程进行的写入对于其他线程可见。在进入同步块之前,我们需要获取监视器,该监视器具有使本地处理器缓存无效的作用,以便可以从主内存中重新加载变量。然后,我们将能够看到以前版本中所有可见的写入。

我还记得读过有关在现代Sun VM上进行无竞争的同步很便宜的信息。我对此说法有些困惑。考虑如下代码:

class Foo {
    int x = 1;
    int y = 1;
    ..
    synchronized (aLock) {
        x = x + 1;
    }
}

对x的更新需要同步,但是获取锁是否也从缓存中清除y的值?我无法想象是这种情况,因为如果这是真的,锁条之类的技术可能无济于事。或者,JVM是否可以可靠地分析代码以确保不使用相同的锁在另一个同步块中修改y,从而在进入同步块时不将y的值转储到高速缓存中?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。