现在我们有了
Load A
StoreStore
Store B是否有可能实际执行命令如下
StoreStore
Store B
Load A如果可能的话,如何解释似乎违反了The Java volatile Happens-Before Guarantee的情况。
据我所知,易失性语义是使用以下JMM内存屏障添加策略实现的
insert a StoreStore before volatile variable write operation
insert a StoreLoad after volatile variable write operation
insert a LoadLoad after volatile variable read operation
insert a LoadStore after volatile variable read operation现在,如果我们有两个java线程,如下所示
螺纹1
Load A
StoreStore
Store volatile B螺纹2
Load volatile B
Load C根据“Java易失性发生-在保证之前”,Load A应该发生在Load C之前,而Load volatile B是Store volatile B之后,但是如果Load A可以被重新排序为“存储易失性B之后”,如何保证Load A is before Load C
发布于 2019-10-01 14:25:38
从技术上讲,Java语言没有内存障碍。相反,Java内存模型是在关系发生之前指定的;有关详细信息,请参阅以下内容:
您正在讨论的术语来自于编者用的JSR-133烹饪本。正如文档所述,它是为编写实现Java内存模型的编译器的人员提供的指南。它解释了JMM的含义,显然并不打算成为正式规范。JLS是规范。
JSR-133食谱中关于内存屏障的部分根据它们约束特定的加载和存储序列的方式对它们进行分类。对于StoreStore障碍,它说:
序列:
Store1; StoreStore; Store2确保在与Store2和所有后续存储指令相关联的数据之前,存储1的数据对其他处理器(即刷新到内存)是可见的。通常,在处理器上需要StoreStore屏障,否则不能保证从写缓冲区和/或缓存到其他处理器或主内存的刷新的严格顺序。
如您所见,StoreStore屏障只约束store操作的行为。
在您的示例中,您有一个load和一个store。StoreStore屏障的语义与load操作无关。因此,您提议的重新排序是允许的。
发布于 2019-10-12 04:31:40
这只是回答你问题的最新部分。
首先,您提供的示例不是Java代码。因此,我们不能将JMM推理应用于它。(只是为了让我们清楚地知道这一点。)
如果您想了解Java代码是如何运行的,请忘记内存障碍。Java内存模型告诉您所有需要做的事情,以便内存读写具有有保证的行为。以及你需要知道的一切,以便对(正确)行为进行推理。所以:
看看你的例子中的伪指令序列,它们没有多大意义。我不认为真正的Java编译器在编译真正的Java代码时会(在内部)使用类似的障碍。相反,我认为在每次易失性写入和每次易失性读取之前都会有一个StoreLoad内存屏障。
让我们考虑一些真正的Java代码片段:
public int a;
public volatile int b;
// thread "one"
{
a = 1;
b = 2;
}
// thread "two"
{
if (b == 2) {
print(a);
}
}现在假设线程“2”中的代码是在线程“1”之后执行的,就会发生这样的情况--在这样的链之前:
a = 1发生-在b = 2之前b = 2发生-在b == 2之前b == 2发生-在print(a)之前除非涉及到其他代码,否则在链之前发生的情况意味着线程“2”将打印"1“。
注意:
https://stackoverflow.com/questions/58185339
复制相似问题