工作的volatile变量

时间:2015-05-19 06:44:09

标签: java multithreading volatile

我试图理解volatile变量的工作。我创建了一个简单的课程" A"它扩展了"线程"并且有一个易变的变量" i"。还有另一个班级" Amain"运行3个线程的类" A"。我在A的run()内运行一个循环,它依赖于这个volatile变量。这是代码。

// Thread

public class A extends Thread {

    public volatile int i = 0;

    @Override
    public void run() {

        while(i<10)
            System.out.println(i++ + "  " + this.getName());
    }
}

// Main Class

public class Amain {

    public static void main(String[] args) {

        A t1 = new A();
        A t2 = new A();
        A t3 = new A();

        t1.start();
        t2.start();
        t3.start();
    }

}

如果在所有线程之间共享易失性值,那么&#34; i&#34;本来应该打印10次。相反,它为每个线程打印10个值,即总共30个值。需要在此代码的上下文中理解volatile的工作。另外,我还可以从任意数量的线程中获取i的10个值(在此代码的上下文中)。

3 个答案:

答案 0 :(得分:7)

在您的情况下,您创建了三个单独的A个对象,每个对象都有单独的i字段,因此此处没有共享状态。如果您希望共享变量,请将其声明为static

public static volatile int i = 0;

请注意,即使变量是易变的,增量也是不安全的。请改用AtomicInteger

答案 1 :(得分:2)

在您的情况下,没有共享状态。即,volatile字段不在线程之间共享。每个线程都有自己的i实例,因此您的代码是线程安全的。如果您将i声明为static,那么它将被共享,然后您就可以看到volatile实际上做了什么。

答案 2 :(得分:0)

使用

volatile关键字,以便访问该变量的所有线程都可以看到该变量的最新更新。

在您的情况下,int i是一个类成员,在main()方法3中创建了class A的单独实例,因此每个线程都有自己的变量i的独立副本。这就是你总共看到30个数字的原因。如果将变量i声明为public static volatile int i = 0;,它将在所有线程之间共享,并且您将不会在控制台中看到30个数字。

为了确保递增操作是原子的,您还需要将i++放在同步块中,或者您可以将i声明为AtomicInteger而不是int

有关详细信息,请参阅Simplest and understandable example of volatile keyword in java