簡體   English   中英

在 ConcurrentHashMap 中使用 Guava 的基於鍵的信號量 vs 信號量

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM