StampedLock 如何对锁定请求进行队列?

问题描述 投票:0回答:1

我正在研究基于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 multithreading concurrency locking
1个回答
0
投票

“Java 并发有这么困难吗?还是我错过了一些明显的事情?”

Java 并发性是否比(例如)C++ 或 Python 并发性更困难,这是一个见仁见智的问题。 但是,是的,在任何允许不同线程直接更新共享数据结构的语言中,并发都很困难

2

。 (仅)支持类 CSP 并发的语言更容易理解和推理。 参考:

    https://en.wikipedia.org/wiki/Communicating_sequential_processes
就您关于公平性的观点而言,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 - ....对于大多数程序员来说。
3 - 如果这对您来说还不够明确,请自己编写一个示例,其中存在(模拟的)无限大的读取请求序列和多个读取器线程。 运行它并查看写入器线程是否会停止,直到读取请求全部耗尽。



© www.soinside.com 2019 - 2024. All rights reserved.