ReentrantLock默认实现是非公平,除非指定公平为true

  1. Lock lock = new ReentrantLock(true);
  2. /**
  3. * Creates an instance of {@code ReentrantLock} with the
  4. * given fairness policy.
  5. *
  6. * @param fair {@code true} if this lock should use a fair ordering policy
  7. */
  8. public ReentrantLock() {
  9. sync = new NonfairSync();
  10. }
  11. public ReentrantLock(boolean fair) {
  12. sync = fair ? new FairSync() : new NonfairSync();
  13. }

一、公平锁

是指多个线程按照申请锁的顺序来获取锁,类似于排队,先来后到。
讲究先来后到,线程在获取锁的时候,如果这个锁的等待队列中已经有线程在等待了,那么当前线程就会进入等待队列中。

二、非公平锁

是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁,在高并发的情况下,有可能会造成优先级反转或者饥饿现象。
优点:吞吐量比公平锁大
对于 synchronized 而言,也是非公平的

三、Synchronized 和 lock 有什么区别

之前是在synchronized中使用唤醒和等待,现在JUC包中的lock也可以使用唤醒和等待。
image.png

1、原始构成

synchronized是关键字属于JVM层面
底层由monitorenter、monitorexit实现(通过monitor对象完成,其实wait/notify等方法也依赖monitor对象,所以只有在同步块或方法中才能调用wait/nofity等方法)
image.png
Lock是具体类(JUC包下的)是API层面的

2、使用方法

  • synchronized:不需要手动去释放锁,当synchronized代码执行完后系统会自动让线程释放锁的占用
  • ReentrantLock:需要用户去手动释放锁,若没有主动释放锁,就有可能导致死锁。

    3、等待是否可中断

  • synchronized:不可中断,除非抛出异常或正常运行完成。

  • ReentrantLock:可中断,1、设置超时方法,trylock(timeout,timeunit unit)2、LockInterruptibly()放代码块中,调用interrupt()方法可中断。

    4、是否公平

  • synchronized:非公平锁

  • ReentrantLock:可公平、可不公平,默认非公平,构造方法传入true则变成公平

    5、锁绑定多个条件Condition

  • synchronized:没有

  • ReentrantLock:用来实现分组唤醒需要唤醒的线程,可以精确唤醒,而不是像synchronized那样要么随机唤醒,要么唤醒全部线程