【JUC】公平锁和非公平锁

文章目录

  • 【JUC】公平锁和非公平锁
    • 1. 公平锁
    • 2. 非公平锁
    • 3. 面试题
      • 3.1 为什么会有公平锁/非公平锁的设计?为什么默认非公平?
      • 3.2 什么时候使用公平锁?什么时候使用非公平锁?

1. 公平锁

公平锁:是指多个线程按照申请锁的顺序来获取锁,这里类似排队买票,先到先得,后来的在后面排队,这是公平锁。主打一个先到先得

示例:

Lock lock = new ReentrantLock(true);

2. 非公平锁

非公平锁:是指多个线程获取锁的顺序并不是按照申请锁的顺序,类似插队买票,有可能后申请的线程比先申请的线程先获取锁,在高并发环境下, 有可能造成优先级反转或者饥饿状态

示例:

Lock lock = new ReentrantLock(false);//或Lock lock = new ReentrantLock();

3. 面试题

3.1 为什么会有公平锁/非公平锁的设计?为什么默认非公平?

  1. 回复挂起的线程到真正锁的获取还是有时间差的,从开发人员来看这个时间微乎其微,但是从CPU的角度来看,这个时间差存在的还是很明显的。所以非公平锁能更充分的利用CPU的时间片,尽量减少CPU的空闲状态时间。
  2. 使用多线程很重要的考量点是线程切换的开销,当采用非公平锁时,当一个线程请求获取同步状态,然后释放同步状态,所以刚释放锁的线程在此刻再次获取同步状态的概率就变得非常大,所以就减少了线程的开销。

3.2 什么时候使用公平锁?什么时候使用非公平锁?

使用公平锁的情况:

  1. 应用场景需要保证任务按照顺序执行,避免饥饿问题;
  2. 锁的持有时间比较长,对性能影响不大;
  3. 能够容忍等待时间较长,对响应时间要求不高。

使用公平锁的情况:

  1. 应用场景需要保证任务按照顺序执行,避免饥饿问题;
  2. 锁的持有时间比较长,对性能影响不大;
  3. 能够容忍等待时间较长,对响应时间要求不高。

需要注意的是,公平锁会带来更多的线程切换和等待开销,会影响性能。因此,一般情况下,默认的锁实现都是非公平锁,只有在确有必要时才使用公平锁。同时,在使用公平锁时需要注意锁的获取和释放的开销较大,需要谨慎使用。