首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JMM关系发生前的重排

JMM关系发生前的重排
EN

Stack Overflow用户
提问于 2016-01-13 19:35:41
回答 2查看 383关注 0票数 3

这是JLS中关于JMM关系之前发生的事情(第17.4.5节):

应当指出的是,在两项行动之间的关系发生之前就出现了一种情况,并不一定意味着它们必须在执行中按这种顺序进行。

我对这一发言的例子感兴趣。

我是否理解这一点,例如:

代码语言:javascript
复制
Thread 1

x = 1
lock M
y = 2                            
unlock M ----------------------->Thread 2:

                                 lock M
                                 z = 3
                                 w = 4
                                 unlock M

显然,在此执行跟踪中,在(x = 1)和(w =4)之间的关系发生之前:

代码语言:javascript
复制
(x = 1) happens-before (w = 4)

在这种情况下,(x = 1)被排序为(w = 4)在执行跟踪中。

Thread 1不使用变量w。因此,我们可以将它放在(x = 1)之前,而不违背Thread 1Thread 2的逻辑。

这是否意味着如果我们重新排序(x = 1)和(w = 4),那么就会发生-在这些语句之间的关系保持之前?

如果你有一些其他的例子,请提供。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-01-14 09:58:39

是的,你是对的,在独立数据发生变化之前,关系就会发生。至于其他的例子,不要忘记,在同样线程中的事件之前也会发生这种情况。规则非常简单:

如果x和y是同一个线程的动作,x以程序顺序出现在y之前,则hb(x,y)。

因此,Java方法中的每条语句都会发生--在后面的每条语句之前,但是当然,JIT编译器和CPU可以自由地重新排序独立的语句(他们实际上经常这样做以优化性能)。有时,您可以从另一个没有发生的线程中观察到这种重新排序--在与当前线程的关系之前。

票数 1
EN

Stack Overflow用户

发布于 2016-01-14 09:59:56

线程1不使用变量w。

您不能假设这是一个原因,因为实际上,Java模型没有考虑在线程隔离上下文()中重新排序指令是否安全。

在没有锁定或内存障碍的情况下,JMM只保证在同一线程中的语句之前发生。

在您的情况下,您对同一个对象(M)有一个锁定机制,因此“发生-之前”发生。

Java中的synchronized (锁)或其他原子变量处理内存屏障、和原子性。关于信息,构造函数中的volatile变量和final变量分配只处理内存障碍。

以这个示例为例,它完全没有内存障碍:

代码语言:javascript
复制
Class Reordering {
  int x = 0, y = 0;
  public void writer() {
    x = 1;
    y = 2;
  }

  public void reader() {
    int r1 = y;
    int r2 = x;
  }
} 

假设这段代码是在两个线程中并发执行的,并且y的读看到值2。因为这个写是在写到x之后,所以程序员可能会假设x的读必须看到值1。然而,写可能已经被重新排序了。如果发生这种情况,那么对y的写入就会发生,两个变量的读取都会随之进行,然后对x的写入就会发生。结果是r1的值为2,而r2的值为0。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34775517

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档