假设我们有n个线程可以访问这个函数,我听说即使布尔值只是一个点翻转,这个过程也不是原子的。在这个函数中,opening = true
是否需要包装在一个同步? opening
是该类的成员。是否需要设置布尔值的关键部分?
boolean opening = false;
public void open() {
synchronized (this) {
while (numCarsOnBridge != 0 || opening || closing) {
// Wait if cars on bridge, opening or closing
try {
// Wait until all cars have cleared the bridge, until bridge opening
wait();
} catch (InterruptedException e) {}
}
// By now, no cars will be under the bridge.
}
if (!opening) {
opening = true; // Do we need to wrap this in a synchronize?
// notifyAll(); // Maybe need to notify everyone that it is opening
try {
sleep(60); // pauses the current thread calling this
} catch (InterruptedException e) {}
synchronized (this) {
drawBridgeClosed = false; // drawBridge is opened
opening = false;
notifyAll(); // Only notify all when state has fully changed
}
}
}
易失性只确保为先前的读取和写入排序。 volatile读取(进入if条件)不会对后续写入的顺序(在if条件中)产生任何保证,因此,如果我们只让'opening'易失性,两个线程仍可能进入相同if条件之前可以重置标志。 – KookieMonster
@KookieMonster - 你是对的 - 我试图确保代码的功能如预期的那样(即'opening = true'对其他线程可见)。代码确实还有其他漏洞,特别是围绕此操作的种族。 – OldCurmudgeon
虽然设置布尔本身本身就是一个原子操作的确是真的,但在这种情况下,注意力放在易变的而不是关键的部分上,这是imho的误导,而这个答案可能会造成混淆。 – kRs