我读过几乎所有的帖子, volatile (即使它不是静态)变量在线程之间共享。当一个线程更新变量时,第二个线程将获取更新后的值。但是,当我在本地计算机上运行以下代码时,运行 java 7 。它没有给出预期的结果
代码-
public class StatciVolatile3 {
public static void main(String args[]) {
new ExampleThread2("Thread 1 ").start();
new ExampleThread2("Thread 2 ").start();
}
}
class ExampleThread2 extends Thread {
private volatile int testValue = 1;
public ExampleThread2(String str) {
super(str);
}
public void run() {
for (int i = 0; i < 3; i++) {
try {
System.out.println(getName() + " : " + i);
if (getName().compareTo("Thread 1 ") == 0) {
testValue++;
System.out.println("Test Value T1: " + testValue);
}
if (getName().compareTo("Thread 2 ") == 0) {
System.out.println("Test Value T2: " + testValue);
}
Thread.sleep(1000);
} catch (InterruptedException exception) {
exception.printStackTrace();
}
}
}
}
结果是 -
Thread 2 : 0
Test Value T2: 1
Thread 1 : 0
Test Value T1: 2
Thread 2 : 1
Test Value T2: 1
Thread 1 : 1
Test Value T1: 3
Thread 2 : 2
Test Value T2: 1
Thread 1 : 2
Test Value T1: 4
正如我们所见,线程 T2 的测试值始终为 1。有人可以帮助我理解为什么会发生这种情况吗?
提前致谢!
我的预期结果是 - 这两个线程都看到更新的值
Thread 1 : 0
Test Value T1: 2
Thread 2 : 0
Test Value T2: 2
Thread 1 : 1
Test Value T1: 3
Thread 2 : 1
Test Value T2: 3
Thread 1 : 2
Test Value T1: 4
Thread 2 : 2
Test Value T2: 4
最佳答案
testValue
是一个实例变量,因此该类的每个实例都有一个单独的变量副本。您已创建两个实例:
new ExampleThread("Thread 1 ").start();
new ExampleThread("Thread 2 ").start();
...并且每个都有自己的变量副本。线程 2 从不更新其值,这就是它保持为 1 的原因。
如果您希望它们共享相同的变量,请将其设为静态
:
private static volatile int testValue = 1;
您的声明:
I have read in almost all the posts that volatile (even if it's not static) variable is shared among the the threads
...表明您对所读内容的误读或误解。如果线程都访问同一个变量,则在线程之间可以看到对 volatile 变量的更改,但这并不意味着实例变量将在实例之间共享。
一些评论指出“testValue++”不是原子操作。一般来说,您确实应该避免对在线程之间共享的 volatile 变量进行此类操作。然而,对于您有限的示例,这实际上并不是一个问题,因为只有一个线程实际上会改变变量的值。
关于java - 对于一个类的多个实例,Volatile 关键字无法按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30642042/