gpt4 book ai didi

java - 动态 ReentrantReadWriteLock-s 用于同步对大量对象的访问

转载 作者:行者123 更新时间:2023-11-30 07:19:35 26 4
gpt4 key购买 nike

我的目标是同步对程序外部的多个(数千)对象的访问。 ReentrantReadWriteLock 提供了一个很好的模型来控制单个对象。然而,就我而言,为每个同步对象创建一个 RWL 对象是疯狂的。幸运的是,同时访问的数量少于一百

因此,我决定创建一个提供如下接口(interface)的服务:

void acquireReadLock(String id) { 
rwl = ....... // get or create RWL object
rwl.writeLock().lock();
}

void acquireWriteLock(String id) {
}

void releaseReadLock(String id) {
}

void releaseWriteLock(String id) {
}

“获取”方法的实现使用简单的延迟初始化来实例化项目的 RWL 对象,或从缓存中获取它。然而,“释放”方法应该包括额外的逻辑来检查是否仍然需要 RWL(= 没有锁)。如果没有,我可以安全地从缓存中删除 RWL,否则内存很快就会被它们淹没。

为了实现此清理逻辑,我需要一种方法来执行适当的检查。方法“getReadLockCount()”和“isWriteLocked()”似乎是合适的候选者,但 JavaDoc 中的这个引用让我很担心:

This method is designed for use in monitoring system state, not for synchronization control.

那么,使用它们来完成我的任务安全吗?还有其他可能的解决方案吗?

最佳答案

单独使用 getReadLockCount() 和 isWriteLocked() 对于您的任务来说并不安全,因为当释放线程调用函数时锁可能是空闲的,但另一个线程可以在释放线程之前获取或开始等待锁从缓存中删除了锁。后一个反对意见 - 另一个线程可能开始等待锁 - 也适用于 tryLock()。

处理此问题的一种方法是使用一个简单的对象作为防护锁,在锁定或解锁读/写锁时,任何线程都需要对其进行同步。当任务完成时,它会锁定防护锁,然后如果读/写锁完全空闲,则移除读/写锁,然后移除防护锁。那时可能有其他线程在等待保护锁,但是一旦它们获取了保护锁,它们就会发现不再有可用的读/写锁,并且它们返回并创建新的保护锁和读/写锁。

创建锁的过程需要以某种方式同步 - 要么全局使用同步块(synchronized block)或函数,要么使用ConcurrentHashMap及其 putIfAbsent() 方法 - 避免尝试同时创建锁的两个线程之间的竞争条件。在尝试将保护锁和新的读/写锁放入缓存之前,线程应该锁定保护锁,如果它从 putIfAbsent() 返回不同的保护锁,则中止新锁创建并等待返回的对象。

就我个人而言,因为这种方法有点复杂,并且如果编写得不完美,可能会导致隐藏的竞争条件,所以我会考虑只为所有外部对象保留读/写锁。至少一百万个外部对象应该没有问题,如果您的进程有几千兆字节的可用内存,那么数千万或数亿个外部对象应该没有问题。

关于java - 动态 ReentrantReadWriteLock-s 用于同步对大量对象的访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37803517/

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