java - Guava 基于键的信号量与 ConcurrentHashMap 中的信号量

标签 java concurrency guava semaphore

我需要一个基于 Semaphore 的 key 我的应用程序中的机制并偶然发现了 Striped.semaphore(int, int) Guava 。但是,它的行为并不像预期的那样。

使用下面的代码,fetch 有时会返回 null。这两种方法都由不同的线程访问。我希望调用 fetch 的线程等到 map 中有可用的 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:

The guarantee provided by this class is that equal keys lead to the same lock (or semaphore), i.e. if (key1.equals(key2)) then striped.get(key1) == striped.get(key2) (assuming Object.hashCode() is correctly implemented for the keys). Note that if key1 is not equal to key2, it is not guaranteed that striped.get(key1) != striped.get(key2); the elements might nevertheless be mapped to the same lock. The lower the number of stripes, the higher the probability of this happening.

您的代码中的基本假设似乎是,如果与特定对象关联的信号量具有许可,则该对象在 map 中有一个条目,但事实并非如此——如果 map 中有一个条目对于恰好与同一 Semaphore 相关联的另一个对象,则该许 cocoa 能会被一个完全不同的对象上的 fetch 获取,该对象实际上在 map 。

关于java - Guava 基于键的信号量与 ConcurrentHashMap 中的信号量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32127688/

相关文章:

java - 将 API 返回的图像保存为 JSON 格式

java - JSP 技巧让模板制作变得更容易?

java - 如何并行运行一组任务并等到所有任务都用 java concurrency utils 完成?

java - 是否有可能使用两个锁且只有一个方法获取两个锁而所有其他方法仅获取一个锁而导致死锁?

java - 如何处理wait()和notify()?

java - Guava Stopwatch类有什么优势?

java - 在关闭时保留 Guava 缓存

java - Android Java,onfinish();让我参与某项 Activity

java - 回调中的 Threadlocal 使用

graph - Guava ValueGraph 的简单示例