Java sleep会导致自旋循环永远循环

Java sleep会导致自旋循环永远循环,java,java-14,Java,Java 14,考虑以下代码: public class Example { @SneakyThrows private static VarHandle init() { MethodHandles.Lookup lookup = MethodHandles.lookup(); return lookup.findStaticVarHandle(Example.class, "x", int.class); } private final static

考虑以下代码:

public class Example {

  @SneakyThrows
  private static VarHandle init() {
    MethodHandles.Lookup lookup = MethodHandles.lookup();
    return lookup.findStaticVarHandle(Example.class, "x", int.class);
  }

  private final static VarHandle X = init();
  private static int x;

  public static void main(String[] args) throws Exception {
    Thread thread = new Thread(() -> {
      System.out.println("Gonna wait till x becomes 1");
      while ((int) X.get() != 1) ;
      System.out.println("x is now 1");
    });
    thread.start();
    new Thread(() -> {
//      System.out.println("Sleeping for 1 second");
//      sleep(1000); // uncomment this statement to reproduce
      X.set(1);
    }).start();
    thread.join();
  }

  @SneakyThrows
  public static void sleep(long ms) {
    Thread.sleep(ms);
  }
}
当我取消注释
sleep时(1000)语句并重新编译以运行它,程序将永远循环。现在要解决这个问题,我可以使用
Thread.onSpinWait()
但是我真的很想了解为什么程序首先要这样做


注意:
@skillythrows
来自lombok,用于使代码易于阅读。它就像一个普通的try-catch块。

所说的“永远停止”是指“永远循环”?
X.get()
没有任何订购授权人。JIT很可能会将代码重写为
int\uu tmp=x;而(uu tmp!=1),永远循环。使用
X.getOpaque()
。我承认我从来没有接触过
VarHandle
s,但是一般来说,如果你在处理一个跨线程变量,你需要一个volatile变量。。。恰好
VarHandle
s有
.getVolatile
.setVolatile
方法来复制这种行为。这取决于具体的用例。如果您想等待其他线程生成某些内容,
.setRelease()
.getAquire()
就足够了。@Powerlord为了安全起见。否则,一些维护人员可能会搞乱语义。无论如何,Johannes在订购方面是对的。你说的“永远停止”是指“永远循环”?
X.get()
没有任何订购授权人。JIT很可能会将代码重写为
int\uu tmp=x;而(uu tmp!=1),永远循环。使用
X.getOpaque()
。我承认我从来没有接触过
VarHandle
s,但是一般来说,如果你在处理一个跨线程变量,你需要一个volatile变量。。。恰好
VarHandle
s有
.getVolatile
.setVolatile
方法来复制这种行为。这取决于具体的用例。如果您想等待其他线程生成某些内容,
.setRelease()
.getAquire()
就足够了。@Powerlord为了安全起见。否则,一些维护人员可能会搞乱语义。不管怎么说,约翰内斯的订货是对的。