[英]Synchronized hashmap access
在我的計算機上,使用Java 8,即使同步了地圖訪問,以下程序也不會停止。 那些同步的塊難道不是嗎?
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
// Broken! - How long would you expect this program to run?
public class StopThread {
private static HashMap<String, String> stopRequested = new HashMap<String, String>();
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
synchronized (stopRequested) {
while (stopRequested.get("stop") == null)
i++;
}
System.out.println(i);
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
synchronized (stopRequested) {
stopRequested.put("stop", "true");
}
}
}
這將永遠運行。 同步塊中的while循環實際上是無限的,因為它首先被輸入-從而禁止再輸入第二個同步塊。
是的,這是預料之中的,您的backgroundThread在主線程之前持有該鎖,並且直到主線程向地圖寫入“停止”時它才會釋放它,主線程需要該鎖將其寫入“停止”,因此基本上這是一個死鎖。
有幾種方法可以解決此僵局,我想您要嘗試的是查看在主線程在映射中寫入“停止”條目之前計數的次數。 您只需在循環的每次迭代中獲取並釋放鎖,這對您的情況就很有意義。
while (stopRequested.get("stop") == null)
synchronized (stopRequested) {
i++;
}
另一種解決方案可能是使用currentHashMap,請查看此鏈接以獲取更多詳細信息
您有兩個線程在stopRequested
上同步。 在任何給定時間僅允許運行一個synchronized
塊。 因為它幾乎永遠是backgroundThread的情況下synchronized
塊第一次運行,它永遠不會退出,因此絕不允許任何其他線程的同步操作stopRequested
。
try {
int i = 0;
synchronized (stopRequested) {
while (stopRequested.get("stop") == null) {
stopRequested.wait();
i++;
}
}
System.out.println(i);
} catch (InterruptedException e) {
throw new RuntimeException(i);
}
// ...
synchronized (stopRequested) {
stopRequested.put("stop", "true");
stopRequested.notify();
}
這樣做的原因是, wait()
會暫時自動地釋放同步鎖,從而允許另一個線程在該對象上進行同步。
請注意, 必須在檢查等待條件的循環中調用wait(),因為即使沒有其他稱為notify()
線程,wait()有時也會返回。 這種“虛假喚醒”是由於某些系統上線程的性質所致。
行為良好的線程會將整個等待循環放在try / catch塊中,因此該線程在被中斷時將退出。 中斷是來自其他某個線程的請求,要求您的線程停止正在執行的操作並干凈地退出。
感謝所有的答案。 確實,這是一個僵局。 工作同步是
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
// Broken! - How long would you expect this program to run?
public class StopThread {
private static HashMap<String, String> stopRequested = new HashMap<String, String>();
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (stopRequested())
i++;
System.out.println(i);
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
synchronized (stopRequested) {
stopRequested.put("stop", "true");
}
}
static boolean stopRequested()
{
synchronized (stopRequested) {
return stopRequested.get("stop") == null;
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.