gpt4 book ai didi

java - 迭代 WeakHashMap

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:01:09 28 4
gpt4 key购买 nike

我同时使用了 WeakHashMap。我想基于一个 Integer 参数实现细粒度的锁定;如果线程 A 需要修改由 Integer a 标识的资源,而线程 B 需要修改由 Integer b 标识的资源,则它们不需要同步。但是,如果有两个线程使用同一个资源,比如说线程 C 也在使用由 Integer a 标识的资源,那么当然线程 A 和 C 需要在同一个锁上同步。

当没有更多线程需要 ID 为 X 的资源时,可以移除映射中针对 key=X 的锁。但是此时可能会有另一个线程进来,尝试使用ID=X的Map中的锁,所以我们需要在加锁/拔锁时进行全局同步。 (这是唯一一个每个线程都必须同步的地方,无论 Integer 参数如何)但是,线程无法知道何时移除锁,因为它不知道它是最后一个使用锁的线程。

这就是我使用 Wea​​kHashMap 的原因:当不再使用 ID 时,可以在 GC 需要时删除键值对。

为了确保我对现有条目的键具有强引用,并且正是构成映射键的对象引用,我需要迭代映射的键集:

synchronized (mrLocks){
// ... do other stuff
for (Integer entryKey : mrLocks.keySet()) {
if (entryKey.equals(id)) {
key = entryKey;
break;
}
}
// if key==null, no thread has a strong reference to the Integer
// key, so no thread is doing work on resource with id, so we can
// add a mapping (new Integer(id) => new ReentrantLock()) here as
// we are in a synchronized block. We must keep a strong reference
// to the newly created Integer, because otherwise the id-lock mapping
// may already have been removed by the time we start using it, and
// then other threads will not use the same Lock object for this
// resource
}

现在,Map 的内容可以在迭代时改变吗?我认为不是,因为通过调用 mrLocks.keySet(),我为迭代范围创建了对所有键的强引用。对吗?

最佳答案

由于 API 没有对 keySet() 进行断言,我建议这样使用缓存:

private static Map<Integer, Reference<Integer>> lockCache = Collections.synchronizedMap(new WeakHashMap<>());

public static Object getLock(Integer i)
{
Integer monitor = null;
synchronized(lockCache) {
Reference<Integer> old = lockCache.get(i);
if (old != null)
monitor = old.get();

// if no monitor exists yet
if (monitor == null) {
/* clone i for avoiding strong references
to the map's key besides the Object returend
by this method.
*/
monitor = new Integer(i);
lockCache.remove(monitor); //just to be sure
lockCache.put(monitor, new WeakReference<>(monitor));
}

}

return monitor;
}

通过这种方式,您在锁定监视器( key 本身)的同时持有对监视器的引用,并允许 GC 在不再使用它时完成它。

编辑:
在评论中讨论了有效载荷之后,我想到了一个有两个缓存的解决方案:

private static Map<Integer, Reference<ReentrantLock>> lockCache = new WeakHashMap<>();
private static Map<ReentrantLock, Integer> keyCache = new WeakHashMap<>();

public static ReentrantLock getLock(Integer i)
{
ReentrantLock lock = null;
synchronized(lockCache) {
Reference<ReentrantLock> old = lockCache.get(i);
if (old != null)
lock = old.get();

// if no lock exists or got cleared from keyCache already but not from lockCache yet
if (lock == null || !keyCache.containsKey(lock)) {
/* clone i for avoiding strong references
to the map's key besides the Object returend
by this method.
*/
Integer cacheKey = new Integer(i);
lock = new ReentrantLock();
lockCache.remove(cacheKey); // just to be sure
lockCache.put(cacheKey, new WeakReference<>(lock));
keyCache.put(lock, cacheKey);
}
}

return lock;
}

只要存在对有效负载(锁)的强引用,对keyCache 中映射整数的强引用就会避免从lockCache 中移除有效负载缓存。

关于java - 迭代 WeakHashMap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28023270/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com