我正在研究基于Java8的
StampedLock
(javadoc此处)锁定缓存,但尽管阅读了StampedLock Idioms等文章,但我在网上找不到令人信服的实现来遵循。
在惊讶于
ReentrantReadWriteLock
不允许将读锁升级为写锁之后,我对Java的多线程和并发产品感觉不太积极,随后又很难找到信誉良好的替代解决方案。
我的问题是,没有明确的声明可以减轻我的担忧,即当有读取请求排队时,
StampedLock
将无限期地阻止写入请求。
查看文档,有 2 条评论引起了我的怀疑。
来自 Javadoc:
StampedLock的调度策略并不总是优先 读者优于作家,反之亦然。所有“尝试”方法都是尽力而为 并且不一定符合任何调度或公平政策。
来自源代码:
* These rules apply to threads actually queued. All tryLock forms
* opportunistically try to acquire locks regardless of preference
* rules, and so may "barge" their way in. Randomized spinning is
* used in the acquire methods to reduce (increasingly expensive)
* context switching while also ....
所以它暗示了一个读写锁队列,但我需要阅读并消化整个 1500 行源代码才能解决它。
我认为它一定在那里,因为我发现了一篇很好的基准测试文章,它表明
StampedLock
是进行多次读取/少量写入的方法。但我仍然担心,因为缺乏在线报道。
从根本上来说,我想我期望有一个可以按照 javadoc 即插即用的实现,但最终我还是在网上扎根,想知道为什么在任何地方都没有循环的示例
StampedLock#tryOptimisticRead()
- 即使是基准文章中的代码不会这样做。
Java 并发有这么困难吗?还是我错过了一些明显的东西?
“Java 并发有这么困难吗?还是我错过了一些明显的事情?”
Java 并发性是否比(例如)C++ 或 Python 并发性更困难,这是一个见仁见智的问题。 但是,是的,在任何允许不同线程直接更新共享数据结构的语言中,并发都很困难
2。 (仅)支持类 CSP 并发的语言更容易理解和推理。 参考:
就您关于公平性的观点而言,Java 中的大多数形式的锁定确实不能保证
。 事实上,与线程调度有关的许多事情都是(故意)“松散指定的”。 但编写避免这些问题的代码并不困难......一旦您了解了这些库以及如何使用它们。
关于 StampedLock
我的问题是,没有明确的声明可以减轻我的担忧,即当有读取请求排队时,
StampedLock
将无限期地阻止写入请求。
没有这样的说法3,因为这种行为是可能的。 这是通过仔细阅读
StampedLock
API 文档得出的。 例如,它说:
“StampedLock
的日程安排政策并不总是偏爱读者而不是作家,反之亦然。”简而言之,没有任何东西可以保证不定时的
writeLock
最终会获得锁。
如果您需要绝对避免读者导致作家饥饿的情况,那么就不要使用
writeLock
和readLock
。 您可以使用
tryOptimisticRead
代替 readLock
。 或者您可以设计并实现不同的同步机制。
最后,您似乎暗示
StampedLock
提供一种直接处理您的场景的方法和/或该文档应该专门向非专家用户解释如何处理它。 我提请人们注意这一点:
“StampedLocks 设计用作线程安全组件开发中的内部实用程序。”。您很难找到相关示例,这并不是 javadoc 的错。 如果有的话,它支持这样的推论:该 API 仅供专家使用(仅)...
1 - 我的观点是,Java 的并发支持至少比大多数其他同类语言更容易推理。 Java 内存模型(JLS 第 17.4 章)有很好的说明,Goetz 等人的《Java Concurrency In Practice》很好地解释了并发编程的来龙去脉。
2 - ....对于大多数程序员来说。