公平锁提供了一种绝对等待时间公平的机制,锁永远会被同步等待队列中等待时间最长的获取到,
这样可以保证每个在等待的线程在程序不退出的情况下都可以获取到锁。
但是每一个请求的锁的线程都将进入到同步等待队列中阻塞休眠,线程的休眠和唤醒需要耗费额外的时间,会降低效率,降低吞吐量
(整个在同步等待队列中阻塞休眠的操作不是绝对的,只有所没有被占有,并且同步等待队列为空时可以直接获取锁或者递归调用同一个线程获取锁)
简单看下hasQueuedPredecessors()方法,这里只解释满足公平锁加锁条件的情况
/** * Queries whether any threads have been waiting to acquire longer * than the current thread. */ //这个方法是再AQS中提供的用来判断线同步等待队列中是否还有等待时间比当前线程等待时间更长的线程 //tail是队列的尾节点,head是头节点,每个节点会代表一个线程首尾节点除外 //再tryAcquire中我们希望它返回的时false那么看下返回false代表那种情况 //返回false要求 h != t && ((s = h.next) == null|| s.thread != Thread.currentThread())为false,那么要么h==t就是头尾节点是同一个,队列为空 //要么(s = h.next) == null|| s.thread != Thread.currentThread()为false, //这就要求h.next!=null 并且h.next就是当前线程,也就是说队列中第一个等待获取锁的线程就是当前线程 //那么就可以直接加锁; public final boolean hasQueuedPredecessors() { // The correctness of this depends on head being initialized // before tail and on head.next being accurate if the current // thread is first in queue. Node t = tail; // Read fields in reverse initialization order Node h = head; Node s; return h != t && ((s = h.next) == null || s.thread != Thread.currentThread()); } 公平锁的加锁在公平锁的同步器中提供了lock()方法用来进行加锁操作,
可重入锁进行加锁的方法也确实是调用同步器的lock()来实现加锁