假設我們有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