Java 为什么关于线程的代码显示a=1和b=3?为什么要加一个“;易挥发;没有';不行?
代码如下:Java 为什么关于线程的代码显示a=1和b=3?为什么要加一个“;易挥发;没有';不行?,java,multithreading,thread-safety,atomic,volatile,Java,Multithreading,Thread Safety,Atomic,Volatile,代码如下: public class ThreadCacheSample { int a = 1; int b = 2; public void change() { a = 3; b = a; } public void print() { if (a == 1 && b == 3) { // why this is happening?
public class ThreadCacheSample {
int a = 1;
int b = 2;
public void change() {
a = 3;
b = a;
}
public void print() {
if (a == 1 && b == 3) {
// why this is happening?
System.out.println("Thread[" + Thread.currentThread().getName() + "]Confused1 : a = 1, b = 3");
} else if (a == 3 && b == 2) {
// why this is happening, too?
System.out.println("Thread[" + Thread.currentThread().getName() + "]Confused2 : a = 3, b = 2");
} else {
System.out.println("Thread[" + Thread.currentThread().getName() + "] b=" + b + ";a=" + a);
}
}
public static void main(String[] args) {
// create many many threads
while (true) {
// create test every time, to make sure a is 1 and b is 2 again
final ThreadCacheSample test = new ThreadCacheSample();
// one thread for changing
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
test.change();
}
}).start();
// one thread for printing
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
test.print();
}
}).start();
}
}
}
结果应该是a=1、b=2或a=3、b=3
我的问题是:
public class ThreadCacheSample {
volatile int a = 1;
volatile int b = 2;
...
}
p、 这不是一个关于如何修复代码的问题。这是关于为什么会出现奇怪的结果 添加volatile会分别增加
a
和b
修改的可见性(以及在修改可见性之间添加排序依赖性)。然而,它并没有在它们的组合修改中添加任何种类的“原子性”。无论是否“易失性”,修改a
和修改b
(以及读取a
和读取b
)仍然是独立的操作
您的两个“困惑”答案都是可能的:
案例1:
注意,如果没有volatile,您甚至可以得到更古怪的答案,比如打印线程看到“a==1,b==3” 你的书面陈述是错误的。它们不表示
if
中的条件。另外,您可能希望首先在局部变量中捕获它们的值,然后仅对局部变量进行操作。对不起,您所说的“您的打印语句是错误的。它们不代表if中的条件”是什么意思?它们都打印]混淆1:a=1,b=3
。非常好。感谢您这是一个强制性的提醒,“我认为volatile会使每个线程只访问主内存,而不是它们自己的工作内存。”请描述volatile
在一个假设的CPU中的行为,该CPU与现代计算机中的实际CPU工作方式几乎没有相似之处,volatile
实际上并不强制任何东西进入主内存。(这很好。现代CPU上有很多核心间通信,主内存非常慢。如果真正的CPU以这种方式工作,那将是一场灾难!)volatile
在这里有什么区别吗?按照编码方式,两个线程都可以访问相同的变量。如果有什么原因的话,它可能会因为每次修改时的直写而运行较慢。@JanezKuhar-我不确定“访问变量”是什么意思,但volatile确实排除了一种可能性,正如我在上一句中提到的。当然,volatile确实会影响性能。你说得对,如果使用volatile
,它就不能打印a=1,b=3,我的错。