我需要確保多個線程不會同時嘗試訪問同一個資源。我有一堆這些資源,所以我想爲每個資源(而不是一個全局鎖)分別設置一個鎖對象,以便線程不會不必要地阻塞彼此。在一個id上同步並刪除
埃迪介紹了這https://stackoverflow.com/a/659939/82156使用ConcurrentMap.putIfAbsent()
一個很好的解決方案。
// From https://stackoverflow.com/a/659939/82156
public Page getPage(Integer id) {
Page p = cache.get(id);
if (p == null) {
synchronized (getCacheSyncObject(id)) {
p = getFromDataBase(id);
cache.store(p);
}
}
}
private ConcurrentMap<Integer, Integer> locks = new ConcurrentHashMap<Integer, Integer>();
private Object getCacheSyncObject(final Integer id) {
locks.putIfAbsent(id, id);
return locks.get(id);
}
但是,該實現的一個問題是散列映射將無限增長。有沒有辦法在線程完成時刪除散列鍵而不會影響併發性?
和'locks.remove(id,id)'有什麼問題? – OldCurmudgeon
鎖定圖將比實際緩存小得多。是否有機制清理緩存?如果是這樣,它應該也可以清理鎖定圖。 – flup