场景:一个线程运行完毕,准备去等待队列中唤醒(unpark)线程。
公平锁:
当hasQueuedPredecessors 返回false时,则表示不需要去排队,会直接进行cas操作去修改state状态
hasQueuedPredecessors解析
当hasQueuedPredecessors返回false:
h和t相等:一.当队列未初始化时头节点和尾节点都为null,固然相等;二.当队列已经初始化并且已经有线程产生过队列,并且线程已经释放了state状态置为0,则头节点和尾节点都指向同一个节点,即傀儡节点,这个节点是没有线程属性的。
h和t不相等,(s = h.next) == null 和s.thread != Thread.currentThread() 都为false,整个方法才能放回false
当头节点和尾节点不同时,说明队列肯定有>=2数量的节点,则头节点的next节点肯定不等于null,则第一个条件返回了false。
当前线程和next节点的线程相等时返回false,说明当前线程占有了锁,无需排队,方法直接放回false,直接通过compareAndSetState修改state状态。
当hasQueuedPredecessors返回true:
h和t不相等,表示队列中有>=2数量的节点。
h.next为null时,说明刚好有线程在操作队列把头节点的next节点脱离队列,则表示已经该线程正在修改state,所以需要排队,或者next.thread不为当前线程时说明已经有线程修改完state,把node节点的线程置为自己的线程,则当前线程也需要去排队。
非公平锁:
当非公平锁调用lock方法时,一开始就去尝试修改state,如果成功则直接占有状态,并且设置当前线程,不管是刚刚进入的直接去拿锁或者后面实现的tryAcquire的方法都没有检查是否需要排队的操作,所以这是非公平锁和公平锁最主要的区别,当线程释放锁成功,公平锁会去检查自己是否要去排队,只要其他线程比当前线程快或者当前有等待队列,则直接去排队;非公平锁则不一样,线程会去尝试拿锁,不管当前有没有正在等待的队列,一旦拿锁成功,表示插队成功,非公平的意义体现了。如果拿锁失败,并且当前有队列,则该线程会插入队尾。插入队列以后,队列中的线程顺序都是固定无法改变的。