首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >任意键的锁处理程序

任意键的锁处理程序
EN

Stack Overflow用户
提问于 2017-01-28 00:13:49
回答 7查看 1.8K关注 0票数 16

我有实现任意键的“锁处理程序”的代码。给定一个key,它确保一次只有一个线程可以调用那个(或等于) process (这在这里意味着调用externalSystem.process(key)调用)。

到目前为止,我的代码如下:

代码语言:javascript
运行
复制
public class MyHandler {
    private final SomeWorkExecutor someWorkExecutor;
    private final ConcurrentHashMap<Key, Lock> lockMap = new ConcurrentHashMap<>();

    public void handle(Key key) {
        // This can lead to OOM as it creates locks without removing them
        Lock keyLock = lockMap.computeIfAbsent( 
            key, (k) -> new ReentrantLock()
        );
        keyLock.lock();
        try {
            someWorkExecutor.process(key);
        } finally {
            keyLock.unlock();
        }
    }
}

我知道这段代码可以通向OutOfMemoryError,因为没有人清楚的地图。

我在思考如何制作地图,它将累积有限数量的元素。当超过限制时,我们应该用新的访问元素替换最旧的访问元素(此代码应该与作为监视器的最旧元素同步)。但是我不知道如何进行回调,它会告诉我超出了限制。

请分享你的想法。

P.S.

我重读了这个任务,现在我发现我有一个限制,handle方法不能被调用超过8个线程。我不知道它对我有什么帮助,但我只是提到了它。

P.S.2

@Boris给了蜘蛛一个很好的简单的解决方案:

代码语言:javascript
运行
复制
} finally {
      lockMap.remove(key);
      keyLock.unlock();
}

但是在Boris注意到我们的代码不是线程安全的之后,因为它破坏了行为:

让研究用同样的键调用3个线程:

  1. Thread#1获取锁,现在在map.remove(key);
  2. Thread#2使用等于键调用之前,因此它在thread#1释放锁时等待。
  3. ,然后thread#1执行map.remove(key);。在此之后,thread#3调用方法handle。它检查map中是否没有这个键的锁,因此它创建新的锁并获取它。
  4. Thread#1会释放锁,因此thread#2会获取它。

因此,对于等于键,可以并行调用thread#2和thread#3。但这不应该被允许。

为了避免这种情况,在映射清除之前,我们应该阻塞任何线程来获取锁,而等待集中的所有线程都没有获取并释放锁。看起来它需要足够复杂的同步,这将导致算法工作缓慢。也许当map大小超过某个限制值时,我们应该不时地清除map。

我浪费了很多时间,但不幸的是,我不知道如何做到这一点。

EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41898355

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档