Java 同步锁和重入锁之间的区别?

Java 同步锁和重入锁之间的区别?,java,thread-safety,Java,Thread Safety,我在Java中使用了synchronized关键字和重入锁,但我不理解它们之间的区别,也不知道哪种锁适用于给定的情况 我如何决定什么时候应该使用synchronized以及什么时候应该使用重入锁?我一直认为同步是“阻力最小的黑客”。它只是工作,而且大多数人都知道它是如何工作的,但是它有一些弱点,可能会在高并发性下影响您的设计。其中最重要的一点是,任何客户端都可以有效地直接访问对象的同步锁,这意味着如果他们抓住并持有它,其他客户端就不能。换句话说,默认同步实现的锁定有效地“发布”对象的内部锁定机制

我在Java中使用了
synchronized
关键字和重入锁,但我不理解它们之间的区别,也不知道哪种锁适用于给定的情况


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

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

如果将可重入锁设置为类的内部锁(或者只是不使用synchronized,而是在构造函数中新创建的某个内部对象上执行类似于同步的操作),则可以消除发布内部锁机制的副作用,随着类的发展,您必须记住在何处应用此内部同步,这增加了复杂性。

A是:

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

扩展功能包括:

  • 每个监视器具有多个监视器的功能。使用synchronized关键字的监视器只能有一个。这意味着可重入锁支持多个wait()/notify()队列
  • 制造锁的能力。同步块是不公平的。 “[fair]锁倾向于授予对等待时间最长的线程的访问权限。否则,此锁不保证任何特定的访问顺序。”

  • 检查锁是否被保持的能力
  • 获取等待锁的线程列表的能力
  • 可重入锁的缺点是:

  • 需要添加导入语句
  • 需要在try/finally块中包装锁获取。这使得它比synchronized关键字更难看
  • synchronized
    关键字可以放在方法定义中,这样就不需要减少嵌套的块
  • 摘要


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

    这个站点清楚地提到了Java中可重入锁和同步关键字之间的区别。我只是从那里复制粘贴

    1) ReentrantLock和synchronized关键字之间的另一个显著区别是公平性。synchronized关键字不支持公平性。任何线程在释放后都可以获得锁,不能指定任何首选项,另一方面,您可以在创建ReentrantLock实例时通过指定Fairity属性使ReentrantLock公平。公平性属性在争用情况下为等待时间最长的线程提供锁

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

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


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

    “任何客户端都可以有效地直接访问对象的同步锁”,前提是对可访问的方法应用
    synchronized
    修饰符,如果在不可访问的锁对象上使用
    同步的
    块,则不会。是的。我就是这么说的。如果在方法上使用默认的synchronized关键字,则实际上是在发布锁。要解决此问题,请将同步块设置为内部。