我有一个异步更新的HashMap。我需要执行涉及地图的操作,这需要地图在任务期间不会改变状态,例如根据地图内容对值进行排序。
是否有一种锁定地图的方法,以便只能发生阻塞所有写入线程的读取,因此在解锁映射后,所有修改都会发生?锁需要能够在我使用ConcurrentHashMap的同时允许多个线程写入,并且我想利用ConcurrentHashMap的好处。
答案 0 :(得分:4)
ConcurrentHashMap不提供方法调用之间的线程安全性,仅在单个调用中提供。因此,如果要在执行操作时保持映射不变,则需要使用自己的锁将调用包装到地图中。
例如,使用ReadWriteLock:
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
更新地图时
readWriteLock.writeLock().lock();
// do the updates
readWriteLock.writeLock().unlock();
当你想要从地图上阅读时
readWriteLock.readLock().lock();
// perform the read and its operations that rely on the map not changing
readWriteLock.readLock().unlock();
答案 1 :(得分:3)
为什么不使用受ConcurrentHashMap
保护的ReentrantReadWriteLock
但向后使用?
myLock.writeLock().lock();
try {
return myMap.get(...);
} finally {
myLock.writeLock().unlock();
}
和
myLock.readLock().lock();
try {
myMap.put(..., ...);
} finally {
myLock.readLock().unlock();
}
这非常难看,需要在评论中进行覆盖,以便警告一位不知情的后续开发人员,当你持readLock
时正在写作,并在持writeLock
时阅读但我不知道看看为什么它不起作用。
为了清楚起见,您甚至可以编写自己的InversedReentrantReadWriteLock
来包装真实ReentrantReadWriteLock
以反转调用并使代码更具可读性。
如果像@GPI建议的那样,您希望处于读取模式或写入模式但保留该模式下的并发性,则可以使用AtomicInteger
或AtomicLong
来实现锁定。正值可表示处于读取模式,而负值写入模式。为零表示锁可以进入任一模式。这会立即变得更加复杂,因为您必须自己实现锁定,而上面概述的并发写入独占读取解决方案仅依赖于现有的API类。 (我相信如果你愿意,我可以解决一个问题,但我不能立即提供答案)
答案 2 :(得分:0)
如何将HashMap包装到一个放置某种
的类中boolean isLocked
假设你想从一个线程开始阅读过程,你可以检查这个锁
if(!myClass.getLockState())
{ //perform whatever you want to do }
如果确保所有线程都使用相同的myClass
对象,这可能是锁定/解锁hashMap的简单解决方案。