有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java查询可重入锁相对于同步块的缺点

我正在阅读java中可重入锁和同步块之间的比较。我正在浏览互联网上的各种资源。我发现在同步块上使用可重入锁的一个缺点是,在前一个例子中,您必须显式地使用try finally block对finally块中获取的锁调用unlock方法,因为您的关键代码部分可能会抛出异常,这可能会造成大麻烦,如果线程没有释放锁,而在后一个线程中,JVM本身负责在出现异常时释放锁

我不太相信这个缺点,因为使用try finally block没什么大不了的。因为我们在ex(流关闭等)中已经使用了很长时间。有人能告诉我重入锁相对于同步块的其他缺点吗


共 (2) 个答案

  1. # 1 楼答案

    ReentrantLock是针对不同用例的不同工具。虽然这两种方法都可以用于大多数同步问题(这就是它们的用途),但它们有不同的优点和缺点

    Synchronized最简单不过了:你写Synchronized,就这样。对于现代JVM来说,它的速度是合理的,但有一个缺点,即它会让所有试图进入同步块的线程暂停,不管它们是否真的需要。如果您经常使用synchronized,这会显著降低多线程的速度,最糟糕的情况是,单线程执行会更快

    由于线程问题只有在有人在写而其他人在读/写同一数据段时才会发生,因此程序经常会遇到这个问题,理论上它们可以在没有同步的情况下运行,因为大多数线程只是读取,但偶尔会有一次写入,这会强制执行同步块。这就是锁的用途:您可以更好地控制实际同步的时间

    基本的ReentrantLock允许——除了构造函数中的一个公平参数之外——您可以决定何时释放锁,并且可以在多个点上执行,以便在最适合您的时候执行。它的其他变体,如ReentrantReadWriteLock,允许您进行许多不同步的读取,除非有写入操作。缺点是,这在Java代码中得到了解决,这使得它明显比“本机”同步块慢。这就是说:如果你知道使用这个锁的优化增益大于损失,你应该只使用它

    在正常情况下,只有在实际监控的情况下,才能通过运行探查器以复杂的方式检查前后的速度来判断速度的差异

  2. # 2 楼答案

    synchronized对于低竞争或最小竞争几乎总是更快,因为它允许JVM执行一些优化,例如biased lockinglock elision和其他优化。以下是其工作原理的更多细节:

    假设某个监视器由线程A持有,线程B请求该监视器。在这种情况下,监视器将其状态更改为^{。简而言之,这意味着所有试图获取该监视器的线程都将在操作系统级别等待设置,这相当昂贵

    现在,如果线程A在线程B请求之前释放了监视器,那么所谓的rebias操作将由廉价(在现代CPU上)的compare-and-swap操作执行

    让我们看看^ {< CD7> }。每个线程调用lock()lockInterruptibly()方法,通过CAS操作进行锁定尝试

    结论:在低争用情况下,首选synchronized。在高争用情况下,首选ReentrantLock。对于所有的案例,很难肯定地说,考虑执行基准来找出哪种解决方案更快。