![](/img/trans.png)
[英]HashMap vs ConcurrentHashMap vs LoadingCache(Guava)
[英]Key based Semaphores with Guava vs Semaphores in a ConcurrentHashMap
我的應用程序中需要一個基於鍵的信號量機制,並且偶然發現了Guava 的 Striped.semaphore(int, int) 。 但是,它的行為並不像預期的那樣。
使用以下代碼,fetch 有時會返回 null。 這兩種方法都由不同的線程訪問。 我希望調用 fetch 的線程等待直到地圖中的 Blubb 可用。
private final Striped<Semaphore> semaphores = Striped.semaphore(64, 0);
private final Map<String, Blubb> blubbs = Collections.synchronizedMap(new HashMap<String, Blubb>());
private Semaphore getSemaphore(final String key) {
return semaphores.get(key);
}
@Override
public void put(String key, Blubb blubb) {
blubb.put(key, blubb);
final Semaphore semaphore = getSemaphore(toUser);
semaphore.release();
}
@Override
public blubb fetch(final String key) {
try {
final Semaphore semaphore = getSemaphore(key);
final boolean acquired = semaphore.tryAcquire(30, TimeUnit.SECONDS);
return blubbs.get(key);
} catch (final InterruptedException e) {
e.printStackTrace();
}
return null;
}
如果我使用以下代碼切換回基本 Java,一切都會按預期進行。
private final Map<String, Semaphore> semaphoresMap = new ConcurrentHashMap<String, Semaphore>();
private Semaphore getSemaphore(final String key) {
Semaphore semaphore = semaphoresMap.get(key);
if (semaphore == null) {
semaphore = new Semaphore(0);
semaphoresMap.put(key, semaphore);
}
return semaphore;
}
我在這里缺少什么? 謝謝
Guava 的Striped
指定多個鍵可能映射到同一個信號量。 來自 Javadoc:
此類提供的保證是相等的鍵導致相同的鎖(或信號量),即 if (key1.equals(key2)) then striped.get(key1) == striped.get(key2)(假設 Object.hashCode () 正確實現了鍵)。 注意如果key1不等於key2,不保證striped.get(key1) != striped.get(key2); 盡管如此,元素可能會映射到同一個鎖。 條紋數量越少,發生這種情況的概率就越高。
您代碼中的基本假設似乎是,如果與特定對象關聯的信號量具有許可,則該對象在映射中具有條目,但事實並非如此——如果映射中存在另一個對象的條目恰好與相同的Semaphore
相關聯,那么該許可可能會被一個完全不同的對象的fetch
,該對象實際上在映射中沒有條目。
'basic java' 示例有一個潛在的競爭條件,computeIfAbsent 是一個原子操作並解決了這個問題:
private final Map<String, Semaphore> semaphoresMap = new ConcurrentHashMap<String, Semaphore>();
private Semaphore getSemaphore(final String key) {
return semaphoresMap.computeIfAbsent(key, (String absentKey) -> new Semaphore(0));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.