ReentrantLock源码分析
目录
1:reentrantLock使用
1.1 构造lock的test模型
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.saytoyou.com.lock; import java.util.concurrent.locks.ReentrantLock; public class LockTest extends Thread { private int a = 1; private ReentrantLock lock; public LockTest(ReentrantLock lock) { this.lock = lock; } @Override public void run() { lock.lock(); try { a = a + 1; System.out.println(Thread.currentThread().getName()+"a===="+a); }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } } }
1.2:使用main方法进行测试
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.saytoyou.com.lock; import java.util.concurrent.locks.ReentrantLock; public class ReentrantLockTestTwo { public static void main(String[] args) { ReentrantLock lock = new ReentrantLock(); LockTest lockTest = new LockTest(lock); for (int i = 1;i<=100;i++){ new Thread(lockTest).start(); } } }
2:开始源码分析
public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
构造reentrantLock模型,可以通过构造函数构造公平锁或者非公平锁
2.1 分析公平锁和非公平锁
非公平锁NoneFairSync方法分析
static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L; /** * Performs lock. Try immediate barge, backing up to normal * acquire on failure. */ final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } }
lock的时候直接尝试setState的值,如果设置成功表示获取到锁,设置独占线程为当前线程,否则进行第二部
2:第二部acquire尝试获取锁,源码如下:
final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { 重入方法,state的值叠加 int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; }
其实acquire主要就是直接获取锁,没有判断等待队列是否有等待线程,和公平锁的区别,
public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
acquireQeued方法就不介绍了,AQS源码有分析
2.2 公平锁源码分析
protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (!hasQueuedPredecessors() && 先判断是否有等待队列线程 compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } }
公平锁先判断是否有等待队列线程,如果有等待队列直接返回false,加入等待队列FIFO
如果没有等待队列才开始尝试获取资源,设置state的值,和非公平锁的不同之处就在这
3:unLock源码分析
public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; }
首先进行tryRelease释放state的值,如果释放成功,进行线程唤醒工作,注意只有当前获取到锁的线程指向head节点,所以释放传入头节点即可
tryRelease源码如下:
protected final boolean tryRelease(int releases) { int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; }
当前的state减去1,如果不是当前线程调用unLock则直接报错,如果等于0说名释放成功,则线程直接重置
3.1:unparksuccessor()方法介绍
private void unparkSuccessor(Node node) { int ws = node.waitStatus; if (ws < 0) compareAndSetWaitStatus(node, ws, 0); Node s = node.next; if (s == null || s.waitStatus > 0) { s = null; for (Node t = tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; } if (s != null) LockSupport.unpark(s.thread); }
不懂的看一看AQS源码,基本就是拿到节点,找到子啊一个节点,进行unpark话逆行,如果状态不正确,就从后往前找一个正确的节点进行释放