【问题标题】:Reordering instruction重新排序说明
【发布时间】:2018-08-28 07:08:42
【问题描述】:

我知道指令重新排序,但在以下链接中 Will this AssertionError never be thrown in this case? 在批准的答案中有一行:

首先使用变量 n 对引用的发布重新排序(没有发生之前,所以这是允许的)。 Thread1 创建 Holder 实例"

我听不懂这条线。谁能解释一下。这种重新排序将如何发生。我知道thread.start() 发生在关系之前。

我对 java 中重新排序的理解是,如果指令在关系之前没有发生,则可以重新排序。

int c=0;
int d=1;

可以重新排序为

int d=1;
int c=0;

但用户解释说,如果thread.starts() 在关系之前不会发生,那么发布引用可能会使用变量 n 重新排序(这是允许的)。我不明白怎么做。引用在其他类中,变量 n 在不同的类中。

【问题讨论】:

  • 我会进一步处理格式化问题。谢谢
  • @Ivan 问题是我无法想象指令重新排序后代码的样子。我假设可以重新排序顺序指令。您可以发布一个 sn-p 指令重新排序后它的外观吗?这会有所帮助。

标签: java concurrency


【解决方案1】:

如果没有happens-before并且在Holder对象完全初始化之前设置了对t.holder的引用,则可能会发生这种情况。在这种情况下,我们可以让一个线程执行

public Holder(int n ) {
    this.n = n;
}

另一个正在执行

if (n != n) {
        throw new AssertionError("This statement is false.");
}

第二个线程读取n 的值两次,所以如果我们幸运(或不幸),第一个线程将在这两次读取之前在构造函数中执行赋值,并抛出异常。

【讨论】:

  • 这件事我已经猜到了。如果以前没有发生过。然后在完全构造对象之前,如果 n!=n,您的线程可能已经开始访问 n 的值。在第一次访问中,它可能将 n 的值读取为 0,而在第二次访问中,可能直到该时间对象已初始化并且 n 的值已设置为 42。因此将抛出错误。那么在这里重新排序是什么意思?
  • 谢谢。现在我明白了。
猜你喜欢
  • 1970-01-01
  • 2020-07-30
  • 1970-01-01
  • 2015-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-31
相关资源
最近更新 更多