应用样例
ThreadA、ThreadB、ThreadC拜访如下逻辑ReentrantLock lock = new ReentrantLock();// == 1.加锁lock.lock();...省略业务解决...// == 2.开释lock.unlock();
非偏心加锁过程
偏心形式,无ThreadD局部逻辑,会间接入队
后续都在具体解释这张图
一、非偏心加锁
1.状态批改
// ## 状态:拜访线程会采纳cas的形式批改state的值,加锁过程0->1private volatile int state;// ## 持有线程:state批改胜利的线程,将被记录。比方,exclusiveOwnerThread=ThreadAprivate transient Thread exclusiveOwnerThread;# NonfairSync 非偏心实现final void lock() { // == 1.cas 批改state状态 0->1(插队1) if (compareAndSetState(0, 1)) // state批改胜利批改持有线程 exclusiveOwnerThread = ThreadA setExclusiveOwnerThread(Thread.currentThread()); else // == 2.构建队列,并阻塞线程 acquire(1);}
2.队列构建
### public final void acquire(int arg) { // a-尝试获取,尝试批改state状态(未获取胜利持续后续逻辑) if (!tryAcquire(arg) // b2-排队获取 && acquireQueued( // b1-新增期待节点,构建“独占”模式队列 addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt();}
a-尝试获取(可能插队的地位)
java.util.concurrent.locks.ReentrantLock.NonfairSync#tryAcquirejava.util.concurrent.locks.ReentrantLock.Sync#nonfairTryAcquirefinal boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); // ## 插队地位 if (c == 0) { if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } // ## 重入,state++ 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;}
b1-新增期待节点,构建“独占”模式队列
class Node { /** 独占 */ static final Node EXCLUSIVE = null; // 指向线程 volatile Thread thread; volatile Node prev; volatile Node next; static final int SIGNAL = -1;
java.util.concurrent.locks.AbstractQueuedSynchronizer#addWaiterprivate Node addWaiter(Node mode) { Node node = new Node(Thread.currentThread(), mode); // Try the fast path of enq; backup to full enq on failure Node pred = tail; // == 2.队列不为空,节点尾插 if (pred != null) { node.prev = pred; if (compareAndSetTail(pred, node)) { pred.next = node; return node; } } // == 1.队列初始构建 enq(node); return node; // 返回尾节点}//== 1.队列初始构建java.util.concurrent.locks.AbstractQueuedSynchronizer#enqprivate Node enq(final Node node) { for (;;) { Node t = tail; // -- A、初始化构建,头尾指针指向空Node if (t == null) { if (compareAndSetHead(new Node())) tail = head; } // -- B、尾插 else { node.prev = t; // cas 批改尾节点指向 if (compareAndSetTail(t, node)) { t.next = node; return t; // 返回头节点 } } }}
b2-排队获取
java.util.concurrent.locks.AbstractQueuedSynchronizer#acquireQueuedfinal boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { boolean interrupted = false; // 循环中 for (;;) { final Node p = node.predecessor(); // ### 前置节点是头节点,有机会尝试获取 //(联合下一个if判断,会自旋两次,也就是说有两次尝试获取机会) if (p == head && tryAcquire(arg)) { setHead(node); p.next = null; // help GC failed = false; return interrupted; } // ### 第1次将waitstatus设置成signal返回false // ### 第2次判断waitstatus==signal返回true if (shouldParkAfterFailedAcquire(p, node) // === 线程阻塞(将来唤醒时,从此处继续执行) && parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed) cancelAcquire(node); }}###private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) { int ws = pred.waitStatus; // -- 第二次调用 if (ws == Node.SIGNAL) return true; if (ws > 0) { do { node.prev = pred = pred.prev; } while (pred.waitStatus > 0); pred.next = node; } // -- 第一次调用 else { compareAndSetWaitStatus(pred, ws, Node.SIGNAL); } return false;}===private final boolean parkAndCheckInterrupt() { LockSupport.park(this); // 以后线程是否被中断 return Thread.interrupted();}
二、开释
java.util.concurrent.locks.ReentrantLock#unlockjava.util.concurrent.locks.AbstractQueuedSynchronizer#release{ // == 1.state还原,exclusiveOwnerThread清空 if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) // == 2.“解除阻塞”执行胜利的节点 unparkSuccessor(h); return true; } return false;}
1.state还原,exclusiveOwnerThread清空
protected final boolean tryRelease(int releases) { // 加锁时线程重入,state++。因而解锁时,state-- int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; // state归0时,开释线程援用 if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free;}
2.“解除阻塞”执行胜利的节点
private void unparkSuccessor(Node node) { int ws = node.waitStatus; // 加锁时,ws=SIGNAL,也就是-1。当初改成0 if (ws < 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; } // ## 开释s节点,也就是head的下一个节点 if (s != null) LockSupport.unpark(s.thread);}
三、偏心加锁
差异一
# FairSync 偏心实现final void lock() { // 无插队操作,间接构建队列 acquire(1);}
再比照下刚刚的非偏心实现,只有else局部
# NonfairSync 非偏心实现final void lock() { // == 1.cas 批改state状态 0->1(插队1) if (compareAndSetState(0, 1)) // state批改胜利批改持有线程 exclusiveOwnerThread = ThreadA setExclusiveOwnerThread(Thread.currentThread()); ### 偏心实现只有这部分逻辑 else // == 2.构建队列,并阻塞线程 acquire(1);}
差异二
public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt();}protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { // ### 偏心实现(多了!hasQueuedPredecessors()):要求无排队状况才有资格尝试进行后续cas操作 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; }}