我试图理解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个值(在此代码的上下文中)。
答案 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。