参考:https://www.jianshu.com/p/f584799f1c77
公平锁:在获取锁之前会先判断等待队列是否为空或者自己是否位于队列头部,满足条件通过才能继续获取锁。否则就进入等待队列中等待 FIFO
非公平锁:线程在获取锁的时候 直接去尝试获取锁,获取不到就自动到队尾等待()。进入到等待队列中的锁也是FIFO(即采用公平锁的方式获取锁)!
比较:1) 线程从可运行状态到运行状态的过程中,会消耗资源且存在一定的延迟,非公平锁就尽量减少CPU的空闲时间
2) 公平锁能很好的控制线程运行的顺序
主要是下面的这张图,一看就明白了
ReentrantLock(https://www.cnblogs.com/DDiamondd/p/11315978.html)对象(可重入锁):默认是非公平锁,如果传入的参数是true则是公平锁
/** * Creates an instance of {@code ReentrantLock}. * This is equivalent to using {@code ReentrantLock(false)}. */ public ReentrantLock() { sync = new NonfairSync(); } /** * Creates an instance of {@code ReentrantLock} with the * given fairness policy. * * @param fair {@code true} if this lock should use a fair ordering policy */ public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
公平锁与非公平锁:
// 非公平锁 2 final boolean nonfairTryAcquire(int acquires) { 3 final Thread current = Thread.currentThread(); 4 int c = getState(); // 获取当前锁的状态 5 if (c == 0) { // 如果state == 0 表示当前锁无线程占用 6 if (compareAndSetState(0, acquires)) { // state 从 0 变成 1 7 setExclusiveOwnerThread(current); // 把当前线程赋给 exclusiveOwnerThread 属性(记录获取该锁的线程) 8 return true; 9 } 10 } 11 else if (current == getExclusiveOwnerThread()) { // ReentrantLock的可重入性 12 int nextc = c + acquires; 13 if (nextc < 0) // overflow 该锁最多支持2147483647个递归锁 14 throw new Error("Maximum lock count exceeded"); 15 setState(nextc); // 修改state的值 16 return true; 17 } 18 return false; // 获取失败 19 } 20 21 // 公平锁 22 protected final boolean tryAcquire(int acquires) { 23 final Thread current = Thread.currentThread(); 24 int c = getState(); 25 if (c == 0) { 26 if (!hasQueuedPredecessors() && //!hasQueuedPredecessors()作用:判断是否为空 或者 该线程是否在队首 27 compareAndSetState(0, acquires)) { 28 setExclusiveOwnerThread(current); 29 return true; 30 } 31 } 32 else if (current == getExclusiveOwnerThread()) { 33 int nextc = c + acquires; 34 if (nextc < 0) 35 throw new Error("Maximum lock count exceeded"); 36 setState(nextc); 37 return true; 38 } 39 return false; 40 }
在第26行中的!hasQueuedPredecessors()方法,这是公平锁与非公平锁不同的关键!非公平锁一上来就直接尝试获取锁,而公平锁还要还看队列是否为空获取是否在队列的首部