Java并发

DPM*_*DPM 0 java multithreading

我有以下问题:为什么在这种情况下第二个线程看到第一个线程何时更改数字的值:

public static void main(String[] args) throws InterruptedException {

    Temp t = new Temp();
    t.go();
}

static class Temp {
    int number = 2;

    public void go() {

        new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                number = 100;
            }
        }).start();

        new Thread(new Runnable() {

            @Override
            public void run() {
                while (true) {
                    System.out.println(number);
                }
            }
        }).start();
    }
}
Run Code Online (Sandbox Code Playgroud)

我期望从第二个线程缓存数值,当第一个线程更改它时,第二个线程将"不知情",并且它将始终打印2!但实际上当第一个线程更改了数字变量时,第二个线程会看到此更改并开始打印100.为什么会这样?我知道第二个线程不会100%确定缓存变量,但在大多数情况下它会这样做.我遗漏的东西很重要.提前致谢.

Tag*_*eev 8

根据Java内存模型,不能保证一个线程更改的值将从另一个线程可见.然而,它并没有反过来说:它可以是可见的.这取决于虚拟机和硬件的实现.如果今天在您的CPU上使用您的VM可见,并不意味着它将始终在每个硬件和每个虚拟机上都可见.你不能依靠这个.

如果您仍想查看效果,可以使用以下代码替换第二个线程代码:

new Thread(new Runnable() {

    @Override
    public void run() {
        while (number < 100) {
        }
        System.out.println(number);
    }
}).start();
Run Code Online (Sandbox Code Playgroud)

这会在HotSpot虚拟机上产生稳定的结果:您的程序永远不会结束(尽管volatilenumber字段上添加关键字将使其在5秒内结束).当然你也不能依赖这个.