1 回答

TA貢獻(xiàn)1802條經(jīng)驗(yàn) 獲得超5個(gè)贊
您的同步有問題。
您使用的同步將使用“this”鎖進(jìn)行同步。你可以這樣想象:
public synchronized void foo() { ... }
是相同的
public void foo() {
synchronized(this) {
....
}
}
這意味著,在進(jìn)入之前,當(dāng)前 Thread 將嘗試獲取“這個(gè)對(duì)象”作為鎖。現(xiàn)在,如果你有一個(gè)工作線程,它也有一個(gè)同步方法(用于向表中添加內(nèi)容),它們不會(huì)完全相互排斥。你想要的是,在下一個(gè)線程開始工作之前,一個(gè)線程必須完成他的工作。
第一個(gè)是 Hashtable,它會(huì)導(dǎo)致程序崩潰并拋出未知的 ConcurrencyIssue。
之所以會(huì)出現(xiàn)這個(gè)問題,是因?yàn)樗赡軙?huì)發(fā)生,即 2 個(gè)線程同時(shí)調(diào)用某些東西。為了說明這一點(diǎn),想象一個(gè)線程對(duì)其調(diào)用 put(key, value) 和另一個(gè)線程調(diào)用 remove(key)。如果這些調(diào)用同時(shí)執(zhí)行(例如由不同的內(nèi)核執(zhí)行),那么生成的 HashTable 會(huì)是什么?因?yàn)闆]有人可以肯定,所以會(huì)拋出ConcurrentModificationException。注意:這是一個(gè)非常簡單的解釋!
當(dāng)我使用 ConcurrentHashMap 時(shí),數(shù)據(jù)是錯(cuò)誤的,因?yàn)樗鼪]有在下一個(gè)對(duì)象與 ConcurrentHashmap 進(jìn)行比較之前及時(shí)刪除條目
ConcurrentHashMap 是一個(gè)實(shí)用程序,為了避免并發(fā)問題,它不是神奇的,多功能的,獨(dú)角獸狩獵,黃油刀。它同步了 mehtod 調(diào)用,這導(dǎo)致只有一個(gè)線程可以在 HashMap 上添加或刪除或執(zhí)行任何其他工作。它不具有與某種鎖相同的功能,這將導(dǎo)致對(duì)分配給線程的映射的訪問。
可能有一個(gè)想要調(diào)用 add 的線程和一個(gè)想要調(diào)用 remove 的線程。ConcurrentHashMap 僅限制了這些調(diào)用,它們不能同時(shí)發(fā)生。哪個(gè)先來?你有權(quán)力(在這種情況下)。你想要的是,一個(gè)線程必須完成他的工作,然后下一個(gè)線程才能完成它的工作。
你真正需要什么取決于你。在java.util.concurrent包帶來的,你可以使用類整體阿森納。例如:
您可以為每個(gè) Map使用一個(gè)鎖。有了這個(gè),每個(gè)線程(排序/刪除/添加或其他)可以首先獲取所述 Map 的鎖,然后在該 Map 上工作,如下所示:
public Worker implements Runnable {
private int idOfMap = ...;
@Override
public void run() {
Lock lock = getLock(idOfMap);
try {
lock.lock();
// The work goes here
//...
} finally {
lock.unlock();
}
}
}
行 lock.lock() 將確保在方法調(diào)用返回后沒有其他線程正在處理 Map 并修改它,因此該線程將具有對(duì) Map 的雙向訪問權(quán)。在您完成刪除正確的元素之前,沒有一種排序。
當(dāng)然,您必須以某種方式持有所述鎖,就像在數(shù)據(jù)對(duì)象中一樣。話雖如此,您還可以在每個(gè)線程中使用信號(hào)量、synchronized(map) 或以 Runnables 的形式在 Map 上制定您的工作,并將它們傳遞給另一個(gè)線程,該線程一個(gè)接一個(gè)地調(diào)用他收到的所有 Runnables。可能性幾乎是無限的。我個(gè)人建議從鎖定開始。
添加回答
舉報(bào)