对象唤醒条件变量是否应该加上volatile修饰符?
Should the volatile modifier be added to the object wake-up condition variable?
请检查下面的示例代码:
private volatile int fActiveTestDeathCount;
synchronized void waitUntilFinished() {
while (fActiveTestDeathCount < testCount()) {
try {
wait();
} catch (InterruptedException e) {
return; // ignore
}
}
}
上面的代码可以正常运行,很好理解,但是为什么下面的代码也可以正常运行呢?
private int fActiveTestDeathCount;
synchronized void waitUntilFinished() {
while (fActiveTestDeathCount < testCount()) {
...
}
}
我认为在多线程执行环境下,每个线程都会复制fActiveTestDeathCount变量。如果没有额外的volatile修饰符,这个变量对其他线程是不可见的,程序应该就不能运行了,但事实并非如此
我尝试分析是不是线程被唤醒后,会自动使线程工作内存中的变量失效,然后从主内存同步数据?但是这需要内存屏障的支持,让我有点疑惑。
这里volatile
既不是必需的也不充分。
为什么还不够?因为它不会阻止一个线程在它被另一个线程修改之前立即检查 fActiveTestDeathCount
,然后不可撤销地决定 wait
以检查它检查后立即发生的事情。
为什么不需要?因为 synchronized
已经在访问 fActiveTestDeathCount
.
的任何两个线程之间建立了“发生在之前”的关系
wait
的重点是提供一个原子“解锁并等待”操作来精确解决这个竞争条件。
请检查下面的示例代码:
private volatile int fActiveTestDeathCount;
synchronized void waitUntilFinished() {
while (fActiveTestDeathCount < testCount()) {
try {
wait();
} catch (InterruptedException e) {
return; // ignore
}
}
}
上面的代码可以正常运行,很好理解,但是为什么下面的代码也可以正常运行呢?
private int fActiveTestDeathCount;
synchronized void waitUntilFinished() {
while (fActiveTestDeathCount < testCount()) {
...
}
}
我认为在多线程执行环境下,每个线程都会复制fActiveTestDeathCount变量。如果没有额外的volatile修饰符,这个变量对其他线程是不可见的,程序应该就不能运行了,但事实并非如此
我尝试分析是不是线程被唤醒后,会自动使线程工作内存中的变量失效,然后从主内存同步数据?但是这需要内存屏障的支持,让我有点疑惑。
这里volatile
既不是必需的也不充分。
为什么还不够?因为它不会阻止一个线程在它被另一个线程修改之前立即检查 fActiveTestDeathCount
,然后不可撤销地决定 wait
以检查它检查后立即发生的事情。
为什么不需要?因为 synchronized
已经在访问 fActiveTestDeathCount
.
wait
的重点是提供一个原子“解锁并等待”操作来精确解决这个竞争条件。