Java并发面试问题之公平锁与非公平锁
非公平锁
先来聊聊非公平锁是啥,现在大家先回过头来看下面这张图。
如上图,现在线程1加了锁,然后线程2尝试加锁,失败后进入了等待队列,处于阻塞中。然后线程1释放了锁,准备来唤醒线程2重新尝试加锁。
注意一点,此时线程2可还停留在等待队列里啊,还没开始尝试重新加锁呢!
然而,不幸的事情发生了,这时半路杀出个程咬金,来了一个线程3!线程3突然尝试对ReentrantLock发起加锁操作,此时会发生什么事情?
很简单!线程2还没来得及重新尝试加锁呢。也就是说,还没来得及尝试重新执行CAS操作将state的值从0变为1呢!线程3冲上来直接一个CAS操作,尝试将state的值从0变为1,结果还成功了!
一旦CAS操作成功,线程3就会将“加锁线程”这个变量设置为他自己。给大家来一张图,看看这整个过程:
明明人家线程2规规矩矩的排队领锁呢,结果你线程3不守规矩,线程1刚释放锁,不分青红皂白,直接就跑过来抢先加锁了。
这就导致线程2被唤醒过后,重新尝试加锁执行CAS操作,结果毫无疑问,失败!
原因很简单啊!因为加锁CAS操作,是要尝试将state从0变为1,结果此时state已经是1了,所以CAS操作一定会失败!
一旦加锁失败,就会导致线程2继续留在等待队列里不断的等着,等着线程3释放锁之后,再来唤醒自己,真是可怜!先来的线程2居然加不到锁!
上述的锁策略,就是所谓的非公平锁!
如果你用默认的构造函数来创建ReentrantLock对象,默认的锁策略就是非公平的。
那如果要实现公平锁的策略该怎么办呢?也很简单,在构造ReentrantLock对象的时候传入一个true即可:
ReentrantLock lock = new ReentrantLock(true)
什么是公平锁?
如果AQS的队列里真的有线程排着队,那我线程3就不能跟个二愣子一样直接抢占加锁了。
因为现在咱们是公平策略,得按照先来后到的顺序依次排队,谁先入队,谁就先从队列里出来加锁!
所以,线程3此时一判断,发现队列里有人排队,自己就会乖乖的排到队列后面去,而不会贸然加锁!
- Top 50 Java 线程并发的面试问题
- java多线程和并发面试问题及答案
- JAVA并发多线程的面试问题及答案(基础部分)
- java-面试- Java并发编程(一)——并发编程需要注意的问题
- JAVA并发多线程的面试问题及答案(基础部分)
- 大白话聊聊Java并发面试问题之volatile到底是什么?
- java并发编程--AbstractQueuedSynchronizer公平锁和非公平锁分析(三)
- Java并发的面试问题合集
- java并发:简单面试问题集锦
- java面试中的高并发的问题
- Java并发编程相关面试问题
- Java并发面试问题
- 大白话聊聊Java并发面试问题之谈谈你对AQS的理解?
- java多线程并发基础面试问题
- java并发库 Lock 公平锁和非公平锁
- 面试问题:关于java并发方面的
- java并发库 Lock 公平锁和非公平锁
- 面试java高级工程师、项目经理等的常见问题
- java面试常见问题
- JAVA程序员面试必须掌握的33个问题