由“易失性”可见性引起的代码执行问题

时间:2019-05-28 04:06:19

标签: java

例如:1

public class Test extends Thread {
    private Boolean stop = false;
    public static void main(String[] args) throws Exception {
        Test test = new Test();
        test.start();
        TimeUnit.SECONDS.sleep(1);
        test.stop = true;
    }
    @Override
    public void run() {
        while (!this.stop) {
        }
        System.out.println("end");
    }
}

这样编写代码,线程将无限执行。但是,在while循环中添加一些内容,并将其更改为如下所示:

例如:2

public class Test extends Thread {
    private Boolean stop = false;
    public static void main(String[] args) throws Exception {
        Test test = new Test();
        test.start();
        TimeUnit.SECONDS.sleep(1);
        test.stop = true;
    }
    @Override
    public void run() {
        while (!this.stop) {
            System.out.println(1);  // Add some code
        }
        System.out.println("end");
    }
}

问:

为什么会这样? ???为什么我可以通过打印句子来打断它,并且不打印就不会被打断。 。 。 。 。 。 。 。 。 。 。 。 。 。请注意,未添加stop volatile。如果添加,则可以在1秒钟后停止。

1 个答案:

答案 0 :(得分:2)

因为stop不是volatile,所以不能保证一个线程所做的更改会被另一个线程看到(除非其他东西提供了类似锁的保证)。这样您将获得无法预测的结果。

如果一个线程对对象的更改需要在另一个线程中可见,则有大量无法进行的优化。但这仅是很小一部分实际代码的要求。因此,Java实现者明智地决定使依赖于该行为的代码表明这一点,并允许对不关心这一点的99.5%的代码进行这些重要的优化。

如果要依靠一个线程对另一个线程可见的更改,则必须使用指定的一种机制来提供此行为。否则,结果将无法保证。