ReentrantLock锁源码解析
Posted djcao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ReentrantLock锁源码解析相关的知识,希望对你有一定的参考价值。
ReentrantLock的常用方法,lock、tryLock和unlock。
截图主要分析部分的源码如下:
public class ReentrantLock implements Lock, java.io.Serializable { private static final long serialVersionUID = 7373984872572414699L; /** Synchronizer providing all implementation mechanics */ private final Sync sync; abstract static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = -5179523762034025860L; abstract void lock(); 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; } 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; } protected final boolean isHeldExclusively() { // While we must in general read state before owner, // we don‘t need to do so to check if current thread is owner return getExclusiveOwnerThread() == Thread.currentThread(); } final ConditionObject newCondition() { return new ConditionObject(); } // Methods relayed from outer class final Thread getOwner() { return getState() == 0 ? null : getExclusiveOwnerThread(); } final int getHoldCount() { return isHeldExclusively() ? getState() : 0; } final boolean isLocked() { return getState() != 0; } /** * Reconstitutes the instance from a stream (that is, deserializes it). */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); setState(0); // reset to unlocked state } } static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L; final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } } static final class FairSync extends Sync { private static final long serialVersionUID = -3000897897090466540L; final void lock() { acquire(1); } 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; } } public ReentrantLock() { sync = new NonfairSync(); } public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); } public void lock() { sync.lock(); } public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } public boolean tryLock() { return sync.nonfairTryAcquire(1); } public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); } public void unlock() { sync.release(1); } }
一、类结构
1.ReentrantLock类有一个内部抽象静态类--Sync,Sync继承AbstractQueuedSychronizer(简称AQS),AQS为jdk并发锁的基类,
2.ReentrantLock有两个构造函数,可以看到默认为NonfairSync(非公平实现),提供构造参数fair可供选择
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(); }
3.NonfairSync和FairSync为Sync的两种实现。具体差别在于重写的两个父类方法,lock()和tryAcquire()。具体差别在后面解释。
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); } } /** * Sync object for fair locks */ static final class FairSync extends Sync { private static final long serialVersionUID = -3000897897090466540L; final void lock() { acquire(1); } /** * 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) { 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; } }
4.ReentrantLock的很多方法都是调用他的成员属性sync来实现的,sync在构造函数中完成初始化确定是公平实现还是非公平实现。
a.ReentrantLock和Sync类为组合关系。又有点代理模式(委托模式)的意思。
b.ReentrantLock的两种不同锁实现只是覆盖了父类的方法,有AQS定义了锁实现的流程,不同子类的不同实现形成不同的功能,有点模板方法的感觉
public void lock() { sync.lock(); }
public void unlock() {
sync.release(1);
}
二、具体方法实现:
1.lock()方法
a.追踪ReentrantLock的lock方法可以看到:
final void lock() {
// 调用Usafe类用cas(compare and swap)设置AQS的statu为1。 在设置state值时先判断state值是否为0,为0才设置1.
// 当设置成功的时候调用AOS方法把当前线程保存为独占线程。
// 当设置失败的时候调用acquire(1)函数,失败情况为,并发下,其他线程先设置为了1.
if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else
//该方法也是FairSync的lock方法的全部实现。
acquire(1); }
b.acquire方法是AQS的获取锁的模板方法,tryAcquire为抽象方法由子类实现,addWaiter是把当前线程添加到队列中,
acquireQueued是for死循环调用tryAcquire获取锁,会在调用两次后阻塞自己线程,并把当前线程所属节点的前置节点的waitStatus置为-1(Signal)。
acquireQueued方法的出参表示执行完方法时的线程是否中断,如果为中断,会调用Thread.currentThread().interupt()。设置当前线程的中断标志
public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
c.公平锁实现的tryAcquire比非公平锁实现复杂,分析公平锁的实现,
1.实现流程是,获取AQS的state,state=0表示还未获取了锁,并且当前的队列没有等待者,才尝试设置state为1.如果state不为0,如果当前锁由当前线程占用,则把state加1.实现可重入功能。
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; }
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());
}
2.unlock实现:
a.追踪ReentrantLock的unlock方法可以看到,具体实现代码在Sync中。
b.tryRelease方法是把AQS的state值减一,采用cas算法,如果AQS的state是0,则返回true,表示当前线程完成释放了锁。
c.当占有锁线程完成释放完锁时(每次重入都需要释放),判断头结点的waitStatus的值,如果非默认值,则表示有其他线程等待,唤醒第一个等待节点的线程。
d.unparkSuccessor()方法就是唤醒链表中waitStatus不为-1(取消状态)的第一个等待节点。
public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; } 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; } 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); }
以上是关于ReentrantLock锁源码解析的主要内容,如果未能解决你的问题,请参考以下文章