ReentrantLock 源码分析
ReentrantLock(重入互斥锁)
public class LockDemo {
static final Lock lock = new ReentrantLock();
public static void main(String[] args) {
lock.lock();
//业务逻辑
lock.unlock();
}
}
分析之前首先了解一下Node
Node为双向列表 head指向头部 tail 指向尾部 pre 上一个线程 next 下一个线程 SHARED 共享锁 EXCLUSIVE独占锁
步骤分析
lock
- 调用ReentrantLock.lock()方法
实际调用的是Sync的lock方法
public void lock() {
sync.lock();
}
- sync.lock()方法
- sync.lock()其实是调用Sync的实现类NonfairSync(非公平锁)和FairSync(公平锁)
以非公平锁为例
/**
* Sync object for non-fair locks
*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
//这里是Sync.lock();
final void lock() {
if (compareAndSetState(0, 1))
//3.将当前线程设置为独占
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
//5. 尝试获取锁
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
- compareAndSetState(0, 1)
- 采用CAS判断当前线程锁状态是否可用
预期值为0 修改成1(如果偏移量不为0则返回false否则返回true)
- acquire(1); 获得锁方法 (以下方法都是抢锁状态)
- 调用Sync父类AbstractQueuedSynchronizer 中的 acquire(int arg)
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
- NonfairSync.tryAcquire(acquires) 尝试获取锁
- Sync.nonfairTryAcquire()
/**
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
*/
final boolean nonfairTryAcquire(int acquires) {
//获得当前线程
final Thread current = Thread.currentThread();
//获取当前线程starte偏移量
int c = getState();
if (c == 0) {
//如果等于0说明当前当前锁对象已被释放
if (compareAndSetState(0, acquires)) {
//CAS成功后 将当前线程设置为独占锁(当前拿到锁)
setExclusiveOwnerThread(current);
return true;
}
}
//不等于0时说明此对象已经有其他线程拿到锁
else if (current == getExclusiveOwnerThread()) {
//如果拿到锁的线程和当前线程相等,说明是同一线程,增加偏移量(重入锁)
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
//将增加后的state存储
setState(nextc);
return true;
}
return false;
}
- 看到这里让我们回顾之前获得锁的方法
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
//addWaiter()为当前线程增加节点
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
- addWaiter(Node.EXCLUSIVE)
/**
* Creates and enqueues node for current thread and given mode.
*
* @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
* @return the new node
*/
private Node addWaiter(Node mode) {
//创建node节点 此时mode=null
//构造方法为:
//Node(Thread thread, Node mode) { // Used by addWaiter
// this.nextWaiter = mode;
// this.thread = thread;
//}
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
//此时为tail==null pred==null 大于第二个线程则不会为null 后面会有说明
Node pred = tail;
if (pred != null) {
node.prev = pred;
//再次做CAS
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
//enq只会执行一次 因为后续的抢占pred都不会为null 后续会有说明
enq(node);
return node;
}
- enq(node)
/**
* Inserts node into queue, initializing if necessary. See picture above.
* @param node the node to insert
* @return node's predecessor
*/
private Node enq(final Node node) {
for (;;) {
//tail为null t==null
Node t = tail;
if (t == null) { // Must initialize
//compareAndSetHead(new Node()): head初始化
if (compareAndSetHead(new Node()))
//第一遍循环肯定执行赋值操作 此时 head 和 tail 都已经被赋值为new Node()
tail = head;
} else {
//循环第二次的时候回走此方法 因T以被赋值
node.prev = t; //将t赋值给prev
if (compareAndSetTail(t, node)) {
//将当前node节点赋值给next
t.next = node;
return t;
}
}
}
}
- acquireQueued(addWaiter(Node.EXCLUSIVE), arg));
/**
* Acquires in exclusive uninterruptible mode for thread already in
* queue. Used by condition wait methods as well as acquire.
*
* @param node the node
* @param arg the acquire argument
* @return {@code true} if interrupted while waiting
*/
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
//阻断默认为false
boolean interrupted = false;
for (;;) {
//获取上一个节点
final Node p = node.predecessor();
//再次尝试抢占锁
if (p == head && tryAcquire(arg)) {
//如果抢占成功 1.将当前node设置为头节点 2.将thread设置为null 3.将prev设置为null
setHead(node);
//将上一个节点的下一个节点设置为null
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
//线程恢复后,如果当前线程被中端过,interrupted为true
interrupted = true;
}
} finally {
if (failed)
//清除无用节点(waitStatus为CANCELLED)
cancelAcquire(node);
}
}
- shouldParkAfterFailedAcquire(Node pred, Node node)
/**
* Checks and updates status for a node that failed to acquire.
* Returns true if thread should block. This is the main signal
* control in all acquire loops. Requires that pred == node.prev.
*
* @param pred node's predecessor holding status
* @param node the node
* @return {@code true} if thread should block
*/
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
//判断上一节点的waitStatus
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
//锁状态直接返回true
/*
* This node has already set status asking a release
* to signal it, so it can safely park.
*/
return true;
if (ws > 0) {
//大于0需要清除出现错误的节点 也就是状态为:CANCELLED
/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
//设置当前节点为上一节点的下一个节点
pred.next = node;
} else {
/*
* waitStatus must be 0 or PROPAGATE. Indicate that we
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
*/
//上一节点的waitStatus小于0 则将上一个节点的waitStatus设置为SIGNAL(-1)
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
- 如果shouldParkAfterFailedAcquire为true则执行parkAndCheckInterrupt())
- 阻塞 调用LockSupport.park(this) 将当前线程挂起
/**
* Convenience method to park and then check if interrupted
*
* @return {@code true} if interrupted
*/
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);//挂起
//获得当前线程是否被中段过(在此线程被唤醒时会接着从这里执行)
return Thread.interrupted();
}
13.在这里回顾一下acquire方法,将以上步骤串联起来
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
//进入如果说明tryAcquire(arg)==false acquireQueued==true
//说明有其他线程在此线程挂起后发起过中断操作,这里此线程已被唤醒,需要响应中断操作
selfInterrupt();
}
14.selfInterrupt();
/**
* Convenience method to interrupt current thread.
*/
static void selfInterrupt() {
Thread.currentThread().interrupt();
}
unlock
- ReentrantLock.lock();
public void unlock() {
sync.release(1);
}
2.release(1) 释放锁
AbstractQueuedSynchronizer工具包中的方法
/**
* Releases in exclusive mode. Implemented by unblocking one or
* more threads if {@link #tryRelease} returns true.
* This method can be used to implement method {@link Lock#unlock}.
*
* @param arg the release argument. This value is conveyed to
* {@link #tryRelease} but is otherwise uninterpreted and
* can represent anything you like.
* @return the value returned from {@link #tryRelease}
*/
public final boolean release(int arg) {
//尝试释放锁
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
//如果当前头部节点不为null 并且 状态不为0
unparkSuccessor(h);
return true;
}
return false;
}
3.tryRelease(arg)
protected final boolean tryRelease(int releases) {
//重入锁次数减1
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
//如果state==0时,说明当前无线程抢占
free = true;
setExclusiveOwnerThread(null);
}
//设置为getState() - releases的值
setState(c);
return free;
}
4.unparkSuccessor(h);唤醒线程 和 lock中的park相互呼应
/**
* Wakes up node's successor, if one exists.
*
* @param node the node
*/
private void unparkSuccessor(Node node) {
/*
* If status is negative (i.e., possibly needing signal) try
* to clear in anticipation of signalling. It is OK if this
* fails or if status is changed by waiting thread.
*/
int ws = node.waitStatus;
if (ws < 0)
//原子操作将当前线程状态设置为0
compareAndSetWaitStatus(node, ws, 0);
/*
* Thread to unpark is held in successor, which is normally
* just the next node. But if cancelled or apparently null,
* traverse backwards from tail to find the actual
* non-cancelled successor.
*/
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)
//唤醒线程对应着lock中park阻塞线程
LockSupport.unpark(s.thread);
}
非公平锁和公平锁的区别
-
lock()方法
- 非公平锁
final void lock() { //这里直接插队 if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); }
- 公平锁
final void lock() { acquire(1); }
-
lock()方法
- 非公平锁
/** * Performs non-fair tryLock. tryAcquire is implemented in * subclasses, but both need nonfair try for trylock method. */ 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()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; }
- 公平锁
/** * Fair version of tryAcquire. Don't grant access unless * recursive call or no waiters or is first. */ protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { //这里会有一层判断 //h != t &&((s = h.next) == null || s.thread != Thread.currentThread()); 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; }