应该使用可以证明“易失性”声明的代码示例

2022-09-03 09:47:43

目前,我无法理解我们何时应该使用来声明变量。volatile

我做了一些研究,并搜索了一些关于它的材料很长一段时间,并且知道当一个字段被声明为易失性时,编译器和运行时会注意到这个变量是共享的,并且对它的操作不应该与其他内存操作重新排序。

但是,我仍然无法理解我们应该在什么情况下使用它。我的意思是,有人可以提供任何示例代码来证明使用“volatile”会带来好处或解决问题吗?


答案 1

下面是一个示例,说明为什么是必要的。如果删除关键字,线程 1 可能永远不会终止。(当我在Linux上的Java 1.6 Hotspot上进行测试时,情况确实如此 - 你的结果可能会有所不同,因为JVM没有义务对未标记的变量进行任何缓存。volatilevolatilevolatile

public class ThreadTest {
  volatile boolean running = true;

  public void test() {
    new Thread(new Runnable() {
      public void run() {
        int counter = 0;
        while (running) {
          counter++;
        }
        System.out.println("Thread 1 finished. Counted up to " + counter);
      }
    }).start();
    new Thread(new Runnable() {
      public void run() {
        // Sleep for a bit so that thread 1 has a chance to start
        try {
          Thread.sleep(100);
        } catch (InterruptedException ignored) { 
         // catch block
        }
        System.out.println("Thread 2 finishing");
        running = false;
      }
    }).start();
  }

  public static void main(String[] args) {
    new ThreadTest().test();
  }
}

答案 2

以下是易失性必要性的规范示例(在本例中为变量。没有它,热点将提升环路()外部的访问,并且永远不会终止。这将发生在大多数服务器 JVM 上。strwhile (str == null)run()

public class DelayWrite implements Runnable {
  private String str;
  void setStr(String str) {this.str = str;}

  public void run() {
    while (str == null);
    System.out.println(str);
  }

  public static void main(String[] args) {
    DelayWrite delay = new DelayWrite();
    new Thread(delay).start();
    Thread.sleep(1000);
    delay.setStr("Hello world!!");
  }
}

推荐