【问题标题】:Not understanding the 'volatile' keyword不理解 'volatile' 关键字
【发布时间】:2014-08-10 01:17:35
【问题描述】:

这是一个线程类。

public class Processor extends Thread {

    public  boolean running = true;
    public void run()
    {
        while (running)
        {
            System.out.println("Hello from " + Thread.currentThread().getName());

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

这是主要的调用程序类

public class ProcessorInvoker {

    public static void main(String[] args) {

        Processor proc1= new Processor();
        proc1.start(); // ---->assuming thread0
        Processor proc2=new Processor();
        proc2.start(); // ---->assuming thread1

        proc1.running=false;
    }
}

我对关键字 volatile 的理解是:当处理器类中的布尔变量不是 VOLATILE 时,此变量的值更改为“false”不会影响 thread1,因为更改为 false-->proc1.running= thread1 看不到 false ,因此 thread1 继续运行,但 thread0 停止。

当布尔变量变为 VOLATILE 时,我的理解是,因为我将布尔变量的值更改为 false,然后 thread1 也看到了更改并将停止,但这在输出中没有发生。我看到相同的输出, thread0 停止但 thread1 仍在运行。我认为两个线程都应该停止。有人可以帮忙澄清一下吗?请告诉我哪里错了。

【问题讨论】:

  • 明确一点:当你不使用 volatile 关键字时,它可能仍然有效(实际上它经常有效,这就是为什么很多人没有编写正确的代码,因为他们没有从中学习痛)。实际上,它可能在某些情况下有效(某些 JVM 版本、某些平台和某些条件,具体取决于代码的重复次数和大小),而在其他情况下则无效。因此,即使您的测试通过,也要始终正确编程。

标签: java multithreading volatile


【解决方案1】:

您有两个Processor 实例,因此当您执行proc1.running=false; 时,您只会停止其中一个线程。您还需要调用 proc2.running=false; 来停止 proc2。

每个线程对象都有自己的实例变量running。您可以将此变量设为静态,然后两者都将停止运行(假设线程运行并在其他代码可能将 running 更改回 true 之前达到 while 条件)。

我认为两个线程都应该停止

当您的消息来源说其他线程应该看到 volatile 变量的最新值时,这并不意味着具有该变量等效版本的其他线程(如 Thread 对象)已更改其变量。它们的意思是,当其他执行线程尝试访问该变量时(无论是在 Thread 对象还是任何其他类型的对象中),它们将看到最新的值。

【讨论】: