【问题标题】:Difference between synchronized and re-entrant lock? [duplicate]同步锁和重入锁的区别? [复制]
【发布时间】:2012-01-30 23:39:11
【问题描述】:

我在 Java 中使用过 synchronized 关键字和重入锁,但我不明白它们有何不同,或者哪种适合特定情况。

我如何决定什么时候应该使用synchronized,什么时候应该使用重入锁?

【问题讨论】:

    标签: java thread-safety


    【解决方案1】:

    ReentrantLock 是:

    具有相同基本行为的可重入互斥锁和 语义作为使用同步访问的隐式监视器锁 方法和语句,但具有扩展功能。

    扩展功能包括:

    1. 每个监视器拥有多个condition variable 的能力。使用 synchronized 关键字的监视器只能有一个。这意味着可重入锁支持多个 wait()/notify() 队列。
    2. 能够锁定fair。同步块是不公平的。

      “[公平] 锁有利于授予对等待时间最长的线程的访问权限。否则此锁不保证任何特定的访问顺序。”

    3. 能够检查锁是否被持有。
    4. 能够获取等待锁的线程列表。

    可重入锁的缺点是:

    1. 需要添加import语句。
    2. 需要将锁获取包装在 try/finally 块中。这使它比 synchronized 关键字更难看。
    3. synchronized 关键字可以放在方法定义中,从而避免需要减少嵌套的块。

    总结

    synchronized 关键字在语法上更好,但可重入锁具有更多功能。

    【讨论】:

      【解决方案2】:

      这个网站清楚地提到了 ReentrantLock 和 Java 中的 synchronized 关键字之间的区别。我只是从那里复制和粘贴。

      http://javarevisited.blogspot.in/2013/03/reentrantlock-example-in-java-synchronized-difference-vs-lock.html

      1) ReentrantLock 和 synchronized 关键字的另一个显着区别是公平性。 synchronized 关键字不支持公平。任何线程一旦释放就可以获取锁,不能指定偏好,另一方面可以通过指定公平属性使 ReentrantLock 公平,同时创建 ReentrantLock 的实例。 Fairness 属性为最长等待线程提供锁,以防发生争用。

      2) 同步锁和可重入锁的第二个区别是 tryLock() 方法。 ReentrantLock 提供了方便的 tryLock() 方法,该方法仅在其可用或未被任何其他线程持有时才获取锁。这减少了在 Java 应用程序中等待锁定的线程阻塞。

      3) ReentrantLock 和 Java 中的 synchronized 关键字之间另一个值得注意的区别是,可以在等待 Lock 时中断线程。在 synchronized 关键字的情况下,线程可以无限期地阻塞等待锁定,并且无法控制。 ReentrantLock 提供了一个名为 lockInterruptibly() 的方法,可以用来在线程等待锁时中断线程。类似地,如果在某个时间段内锁不可用,可以使用带超时的 tryLock() 来超时。

      4) ReentrantLock 还提供了方便的方法来获取所有等待锁的线程列表。

      【讨论】:

        【解决方案3】:

        我一直认为同步是“阻力最小的黑客”。它只是工作,大多数人都理解它是如何工作的,但它有一些弱点可能会影响你在高并发下的设计。其中最重要的是,任何客户端都可以有效地直接访问对象的同步锁,这意味着如果他们抓住它并持有它,其他客户端不能。换句话说,默认同步实现的锁定有效地“发布”了对象的内部锁定机制。玉。这就像为自己造成的拒绝服务做好准备。

        如果你在你的类内部设置了可重入锁(或者只是不使用同步,而是在你想要同步的任何地方在你的构造函数中新建的一些内部对象上进行同步),你删除这个边-发布内部锁定机制的影响,随着类的发展,您必须记住在哪里应用这种内部同步,这增加了复杂性。

        【讨论】:

        • “任何客户端都可以有效地直接访问对象的同步锁”,仅当您将 synchronized 修饰符应用于可访问的方法时,而不是在不可访问的锁对象上使用 synchronized 块时。
        • 是的。这就是我所说的。如果您在方法中使用默认的同步关键字,那么您实际上是在发布您的锁。要解决这个问题,请将同步块设置为内部。
        猜你喜欢
        • 2014-09-30
        • 1970-01-01
        • 2011-08-12
        • 2015-07-25
        • 1970-01-01
        • 2011-09-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多