写锁有优先访问java读写锁中的临界区域吗?[关闭]

Write locks have priority to access the critical region in a java readWrite lock? [closed]

提问人:Juan Gil 提问时间:4/25/2021 更新时间:4/25/2021 访问量:326

问:


想改进这个问题吗?通过编辑这篇文章添加详细信息并澄清问题。

2年前关闭。

我需要编写器线程优先访问关键区域而不是读取器线程,我可以使用 ReadWriteLock 接口来执行此操作吗?

Java 多线程并 ReadWriteLock

评论

0赞 BeUndead 4/25/2021
当您说“具有优先级”时,当写锁到达时,您希望当前在“读锁”下执行的任何内容会发生什么?或者你只是想让一个“作家”跳过队列,这样在作家完成之前,就不会有更多的“读者”开始?
0赞 Juan Gil 4/25/2021
我想让作家跳过队列
0赞 VGR 4/25/2021
Java SE 中只有一个 ReadWriteLock 的标准实现,其文档说:“此类不会对锁访问施加读取器或写入器首选项排序。第三方库中可能存在其他 ReadWriteLock 实现,但 Java SE 似乎没有任何其他实现。
0赞 BeUndead 4/25/2021
@VGR:有两个(StampedLock也可以用作一个)。不过,两者都没有优先权。如果需要,可以使用 ReadWriteLock 编写解决方案,但可能有更简单的方法(例如,使用您已经提到的 Queue)。
0赞 Ben Manes 4/26/2021
Java 的非公平锁都是 barging 锁,这意味着它们试图在回退到排队之前立即获取。这不是优先级,而是一种优化,以避免在不需要公平性的情况下进行上下文切换。公平锁速度较慢,但当需要防止某些线程匮乏时,更可取。

答:

2赞 BeUndead 4/25/2021 #1

虽然没有直接使用 ,但对于这样的事情,最简单的内置方法可能是 ,它确实支持公平性。创建一个公平的,具有(有效)无限数量的应该就足够了:ReadWriteLockSemaphoreSemaphorepermis

private static final Semaphore lock = new Semaphore(Integer.MAX_VALUE, true);

public void doReadLocked() throws InterruptedException {

    // 'Read' lock only acquires one permit, but since there are A LOT,
    // many of them can run at once.
    lock.acquire();
    try {
        // Do your stuff in here...
    } finally {

        // Make sure you release afterwards.
        lock.release();
    }
}

public void doWriteLocked() throws InterruptedException {

    // 'Write' lock demands ALL the permits.  Since fairness is set, this
    // will 'take priority' over other waiting 'read'ers waiting to acquire
    // permits.
    lock.acquire(Integer.MAX_VALUE);
    try {
        // Do your stuff in here...
    } finally {

        // Make sure you release afterwards.
        lock.release(Integer.MAX_VALUE);
    }
}

评论

0赞 Tsyvarev 4/26/2021
根据文档,信号量支持的唯一一种“公平性”是 FIFO 一:当多个线程等待信号量时,较早调用的线程将获胜。所以你的评论看起来不是正确的。(“这将'优先'于其他等待获得许可证的'读取'者。.acquire()lock.acquire(Integer.MAX_VALUE);
0赞 BeUndead 4/26/2021
任何“读取”线程都能够立即获取锁。因此,由于“写入”锁现在是队列中的第一个,因此在写入之前,将无法再获取读锁。这是 OP 要求的行为。但是,如果在第一次写入时第二次写入到达,则可能需要处理更多操作。
0赞 Tsyvarev 4/26/2021
哦,明白了。但。。你测试过你的代码吗?我希望这不会等待,而是立即进行:公平只是等待。lock.acquire();lock.acquire(Integer.MAX_VALUE);
1赞 BeUndead 4/26/2021
@Tsyvarev ideone.com/LvWsBN 我尝试在这里快速检查。看起来它按预期工作,但我可能搞砸了测试用例。:/每个 println 开头括号中的数字是我当时预期的计数。
2赞 Holger 4/26/2021
这并不比公平模式好。当存在挂起时,下一个将在它之后排队,就像当有较旧的写锁尝试时(在公平模式下)将挂起的读锁尝试排队一样。但是,当另一个尝试到来时,它不会超过之前排队的尝试,因此仍然没有写入器优先级。ReentrantReadWriteLockacquire(Integer.MAX_VALUE)acquire()acquire(Integer.MAX_VALUE)acquire()