【问题标题】:Why is this code working without volatile?为什么这段代码在没有 volatile 的情况下工作?
【发布时间】:2015-09-06 12:25:59
【问题描述】:

我是 Java 新手,目前正在学习 volatile。假设我有以下代码:

public class Test
{
    private static boolean b = false;

    public static void main(String[] args) throws Exception
    {
        new Thread(new Runnable()
        {
            public void run()
            {
                while(true) 
                {
                    b = true;   
                }
            }
        }).start();

        // Give time for thread to start
        Thread.sleep(2000);

        System.out.println(b);
    }
}

输出:

是的

这段代码有两个线程(主线程和另一个线程)。为什么其他线程能够修改b 的值,b 不应该是volatile 才能发生这种情况?

【问题讨论】:

  • @fillpant 您给我的链接(据我所知),volatile 保证变量不会在本地缓存。所以在我的代码中因为我​​没有使用volatile,所以应该在本地缓存变量,但是这并没有发生,其他线程的修改被主线程看到了!!
  • 检查这个答案http://stackoverflow.com/questions/4934913/are-static-variables-shared-between-threads。它说,即使变量没有被标记为 volatile ,如果写操作发生在任何其他线程的读操作之前,更新的静态变量将对其他线程可见,这在你的代码中就是这种情况,因为你在主线程上调用 sleep 2 秒,这个时间绰绰有余。移除睡眠电话,您可能会看到零星的结果

标签: java


【解决方案1】:

volatile 关键字保证更改在多个线程中可见,但您将其解释为相反的情况; volatile 关键字的缺失保证了线程之间的隔离,并且没有这样的保证。

此外,虽然您的代码示例是多线程的,但它不一定是并发的。可能是每个线程都缓存了这些值,但在打印结果之前,JVM 有足够的时间传播更改。

【讨论】:

    【解决方案2】:

    您是对的,使用volatile,您可以确保/保证您的 2 个线程将始终从主内存中看到适当的值,而不是线程特定的缓存版本。

    没有volatile,您将失去该保证。每个线程都在使用它自己的缓存版本的值。

    但是,没有什么可以阻止 2 个线程在需要时重新同步它们的内存,并最终查看相同的值(也许)。只是你不能保证它会发生,而且你肯定不能保证它什么时候会发生。但它可能发生在某个不确定的时间点。

    关键是您的代码有时可以工作,有时不能。但是,即使每次您在个人计算机上运行它时,它似乎都在正确读取变量,但同样的代码很可能会在不同的机器上中断。所以你要冒很大的风险。

    【讨论】:

      猜你喜欢
      • 2015-09-17
      • 1970-01-01
      • 2019-02-27
      • 2018-07-20
      • 2013-08-25
      • 1970-01-01
      • 1970-01-01
      • 2010-12-15
      • 2014-03-01
      相关资源
      最近更新 更多