当前位置: 首页 > 知识库问答 >
问题:

volatile是否会在关系发生之前提供其他正常存储和加载?

仲孙英才
2023-03-14

我有一个关于规则之前发生的波动的问题,同样的问题也符合监控规则。根据volatile规则,volatile写入发生在任何后续读取之前。

下面是一个易失性写入和正常后续读取的示例。据我所知,这种易失性写操作应该有一个store-store内存屏障,可以刷新正常的存储到内存,以便其他进程可以看到它(根据DougLea关于JSR-133内存模型的烹饪书)。

所以我的问题是:是否还有一个额外的发生在规则之前,即正常存储的操作1也发生在正常负载的后续操作2之前。

int a;
volatile int x;


public void action1(){
    a = 100;  --- normal store
    x = 123;  ---volatile store
}

public void action2{
    int k = a; ---normal load
}

共有1个答案

傅鸿波
2023-03-14

在正常存储的动作1也发生在正常加载的后续动作2之前的规则之前,是否还有额外的发生?

不,没有。

发生在易失性写入和后续易失性读取之间。

在您的示例中,缺少易失性读取,因此不存在与非易失性读取之前发生关系的链接。因此,您的程序在内存可见性方面没有良好的格式。在某些硬件上,分配给k的值可能不是100

要解决此问题,您需要执行以下操作:

int a;
volatile int x;

public void action1() {
    a = 100;  --- normal store
    x = 123;  ---volatile store
}

public void action2() {
    int x = x; ---volatile load
    int k = a; ---normal load
}

我有另一个问题为什么易失性保证以下正常负载使用内存而不是缓存?java spec没有解释底层,只是陈述了规则,所以我不太理解背后的机制。

Java规范故意不谈论硬件。相反,它指定了格式良好的Java程序的先决条件。如果程序满足这些先决条件,则保证可见性属性。如何满足它们是编译器编写者的问题。

JMM规范的一个结果是,在具有缓存和多个处理器的硬件上,最明显、最有效的实现方法是进行缓存刷新等操作。但这是编译器编写人员关心的问题。。。不是你的。

你(Java程序员)不需要知道缓存、内存障碍等。你只需要理解发生前的规则。但是如果你想从JSR 133食谱的角度理解事情,那么有几件事要记住:

>

Cookbook只与格式良好的程序的行为直接相关。如果必要的事情发生了——在链不存在之前,那么必要的障碍很可能会丢失,其他事情和所有的赌注都会取消。

一个实际的Java实现不一定会像烹饪书那样做。。。嗯。。。推荐。

请注意,对于我的(更正)版本的示例,食谱说在两个负载之间会/应该有一个LoadLoad屏障。

 类似资料:
  • 问题内容: 我有一段代码看起来像这样: 片段A: 根据我的理解,由于的读取不同步,因此如果线程A 在下午1点创建了一个,而线程B 在下午2点进行了读取,则很可能返回0或1(即使线程A在1.05 pm完成了对对象的初始化) )。 所以我添加到: 片段B: 一切都很好,除了我在想,如果我将其修改为 Snippet C ,变量是否仍正确同步? 片段C: 使用 代码片段C ,是否可以保证线程A在下午1:0

  • 实现原子操作,因为java volatile保证发生在关系之前? 我之前读过关于volatile的报道: 如果线程A写入一个易挥发变量,线程B随后读取相同的易挥发变量,那么线程A在写入易挥发变量之前可见的所有变量,在线程B读取易挥发变量后也将可见。 现在,我有两个变量: 现在我有两个线程,一个只写给他们,先写给m_x,再写给m_y;另一个,只从他们那里读,先读m_y,然后,m_x。 我的问题是:写

  • 问题内容: 在Java中,是否有一种优雅的方法可以在运行finally块之前检测是否发生了异常?在处理“ close()”语句时,通常需要在finally块中进行异常处理。理想情况下,我们希望维护两个异常并向上传播它们(因为它们都可能包含有用的信息)。我能想到的唯一方法是在try- catch-finally范围之外有一个变量,以保存对引发的异常的引用。然后将“保存的”异常与在finally块中发

  • 问题内容: 这个问题全都与懒惰有关…我想做这样的事情: 这样我就不必这样做: 有什么办法可以使第一个查询工作?这是我运行它时遇到的错误: 问题答案: 您的意思是在MySQL中您的第一个查询: 产生此错误?: 错误代码:1064。您的SQL语法有错误;请参见语法。检查与您的MySQL服务器版本相对应的手册,以在第1行的’*’附近使用正确的语法 您可以将代码更改为(这不会导致任何错误!): 或到此,如

  • 我想使用regex来查看是否存在某个集合以外的任何字符。 “pvc”返回False 'pd'返回True 'p('返回True 我如何用RE来表达这个?谢了。

  • Docx4j源代码可在https://github.com/plutext/Docx4j获得。 异常跟踪: docx文档很好(由Word2010创建)。我甚至解压了它,看看是否有content_types.xml。就在那儿。