我需要一个基于 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/