问题标签 [reentrantreadwritelock]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
12 回答
42454 浏览

java - Java ReentrantReadWriteLocks - 在读锁中如何安全地获取写锁?

我目前在我的代码中使用ReentrantReadWriteLock来同步对树状结构的访问。这个结构很大,可以同时被许多线程读取,偶尔会修改其中的一小部分——所以它似乎很适合读写习惯。我知道对于这个特定的类,不能将读锁提升为写锁,因此根据 Javadocs,必须在获得写锁之前释放读锁。我以前在不可重入上下文中成功地使用过这种模式。

然而,我发现我无法在不永久阻塞的情况下可靠地获取写锁。由于读锁是可重入的,我实际上是这样使用它的,所以简单的代码

如果我以可重入方式获得了读锁,则可以阻止。每次解锁调用只会减少保持计数,并且只有在保持计数达到零时才会真正释放锁。

编辑澄清这一点,因为我认为我最初解释得不太好 - 我知道这个类中没有内置的锁升级,我必须简单地释放读锁并获得写锁。我的问题是/是,无论其他线程在做什么,调用getReadLock().unlock()可能不会真正释放线程对锁的持有,如果它以可重入方式获得它,在这种情况下,调用getWriteLock().lock()将永远阻塞,因为该线程仍然持有读取锁定并因此阻止自己。

例如,这个代码片段永远不会到达 println 语句,即使在没有其他线程访问锁的情况下运行单线程:

所以我问,有没有一个很好的成语来处理这种情况?具体来说,当一个持有读锁的线程(可能是可重入的)发现它需要进行一些写操作,因此想要“挂起”自己的读锁以获取写锁(根据需要在其他线程上阻塞以释放他们对读锁的持有),然后在相同状态下“拿起”它对读锁的持有?

由于这个 ReadWriteLock 实现是专门设计为可重入的,当可以重入获取锁时,肯定有一些明智的方法可以将读锁提升为写锁吗?这是关键部分,这意味着天真的方法不起作用。

0 投票
2 回答
609 浏览

java - Java ReentrantReadWriteLock 请求

只是一个关于 Java 中的 ReadWriteLocks(特别是 ReentrantReadWriteLock 实现)的快速问题,因为我没有找到清楚的 sun 文档。

如果一个线程在另一个线程请求写锁时持有读锁会发生什么?写锁线程是否必须等待所有当前持有的读锁被释放?此外,在授予和释放写锁之前,是否所有新的读锁请求都会被阻止?

谢谢

0 投票
5 回答
16154 浏览

java - ReentrantReadWriteLock 上的读锁是否足以并发读取 RandomAccessFile

我正在写一些东西来处理对数据库文件的并发读/写请求。

ReentrantReadWriteLock看起来很匹配。如果所有线程都访问共享的RandomAccessFile对象,我是否需要担心并发读取器的文件指针?考虑这个例子:

在 getRecord() 方法中,是否可以使用多个并发读取器进行以下交错?

线程 1 -> getRecord(0)
线程 2 -> getRecord(1)
线程 1 -> 获取共享锁
线程 2 -> 获取共享锁
线程 1 -> 寻求记录 0
线程 2 -> 寻求记录 1
线程 1 ->在文件指针处读取记录 (1)
线程 2 -> 在文件指针处读取记录 (1)

如果使用 ReentrantReadWriteLock 和 RandomAccessFile 确实存在潜在的并发问题,那么替代方案是什么?

0 投票
1 回答
500 浏览

java - java.util.concurrent.locks.ReentrantReadWriteLock 的文档

免责声明:我不太擅长 Java,只是比较 C# 和 Java 之间的读/写锁,以更好地理解这个主题和两种实现背后的决策。

有关于 ReentrantReadWriteLock 的 JavaDoc。它说明了有关锁的升级/降级的以下内容:

  • 锁降级...... 但是,从读锁升级到写锁是不可能的。

它还有以下示例,显示了从读锁到写锁的手动升级:

这是否意味着实际上上面的示例在某些情况下可能无法正确运行 - 我的意思是第 1 行和第 2 行之间没有锁定,并且底层结构暴露于其他线程的更改。所以它不能被认为是升级锁的正确方法还是我在这里错过了什么?

0 投票
2 回答
2687 浏览

java - 用 ReentrantLock 包装 ConcurrentHashMap 读写操作是一个好习惯吗?

我认为在 ConcurrentHashMap 的实现中,已经使用了 ReentrantLock。所以不需要使用 ReentrantLock 来访问 ConcurrentHashMap 对象。这只会增加更多的同步开销。任何意见?

0 投票
3 回答
876 浏览

java - 使用 ReentrantReadWriteLock 和一个布尔标志

我有一个缓存,它预先加载了大量数据(通过后台线程)并且在满之前无法使用(它也会经常重新加载并且在加载期间无法使用)。我希望使用它的类isLoaded()在访问之前检查标志。我使用 ReentrantReadWriteLock (为了简单起见,我在代码中省略了它)进行访问控制,如下所示:

现在在我的另一堂课中,我有一个这样的块:

我真的需要try/catch吗?标志是否有可能设置为 false 并且 readLock try() 会失败?我是否应该为标志而烦恼并抓住异常(因为如果抛出异常,就好像标志为假一样,我基本上会执行相同的代码)。我只是觉得我做错了什么,但我不能把手指放在上面。谢谢。

0 投票
1 回答
506 浏览

java - ReentrantReadWriteLock 类中的 readLock() 或 writeLock() 方法创建的休眠线程会消耗 CPU 周期吗?

我正在使用 Java 6,并阅读 Java Concurrency in Practice。我试图弄清楚在使用这些方法时,等待锁定的休眠线程是否在休眠时使用任何 CPU 周期。有人知道吗?谢谢!

马特

0 投票
2 回答
560 浏览

java - 什么时候可以安全使用 ReentrantReadWriteLock 类的 readLock() 方法?

似乎很清楚,在读取文件时使用 readLock(例如),在写入文件时使用 writeLock 是合适的。但是,如果我有一个比较两个值的操作,例如:

那么是否可以使用 readLock() 而不是 writeLock 来锁定这段代码呢?当然,我没有写任何东西,但我正在比较两个值,这与仅仅读取数据有点不同,因为涉及到一个操作。请记住,“i”或“j”可能随时更改。理论上,如果 writeLock() 没有修改资源,readLock() 只会继续前进,但我可能无法完全理解这个问题的所有复杂性。似乎有一些灰色区域的潜力,所以我想我会得到一些意见。

谢谢大家,

马特

0 投票
2 回答
1478 浏览

java - 等待锁定操作时线程永远阻塞

我正在为两阶段锁定编写一个 java 实现。所以,我正在使用可重入锁(读写锁)。问题是,当线程执行 lock.readLock.lock() 或 lock.writeLock().lock() 并且锁已经被锁定时,即使使用 lock.readLock().unlock 解锁锁,它也会永远卡住它们() 或 lock.writeLock().unlock()。所以,看起来解锁并没有唤醒服务员!!!这是导致问题的代码:

0 投票
3 回答
5771 浏览

java - ReentrantReadWriteLock - 一次有多个读者,一次只有一个作者?

我对多线程环境有些陌生,我正在尝试为以下情况提出最佳解决方案:

我每天早上从数据库中读取一次数据,并将数据存储在 Singleton 对象的 HashMap 中。我有一个 setter 方法,仅在发生日内数据库更改时调用(每天发生 0-2 次)。

我还有一个 getter,它返回地图中的一个元素,这个方法每天被调用数百次。

我担心在清空和重新创建 HashMap 时调用 getter 的情况,从而试图在空/格式错误的列表中找到一个元素。如果我使这些方法同步,它会阻止两个读取器同时访问 getter,这可能是性能瓶颈。我不想对性能造成太大的影响,因为写入很少发生。如果我使用 ReentrantReadWriteLock,这是否会强制任何调用 getter 的人排队,直到释放写锁?它是否允许多个读者同时访问 getter?它会一次只强制一名作家吗?

编码这只是一个问题......