猜想
锁的设计猜想:
1,满足线程的互斥特性
2,同一时刻只能有一个线程进入到加锁的代码 ---》多线程环境下 顺序访问
3,抢占到锁的标记 表示互斥全局变量
4,逻辑处理
抢到锁的逻辑
没抢到锁的逻辑
需要排队(允许有N个线程被阻塞,此时线程处于活跃状态)
通过一个数据结构,存储N个排队的线程
需要等待(让处于排队中的线程,如果没有抢到锁则直先阻塞→释放CPU资源)
如何等待?
1,wait/notify (线程通信机制,无法唤醒指定的某个线程)
2,LockSupport.park()/unpark() 可以阻塞/唤醒某个执行的线程
3,Condition
5,抢到锁的释放过程
AbstractQueuedSynchronizer(AQS) --实现了线程的同步 阻塞 唤醒
两种机制:
共享锁
互斥锁
原理释义:
![](https://i-blog.csdnimg.cn/blog_migrate/fc397ab5d5091acb9a3eddeec17a9cd6.png)
以上线程A释放锁后,一定会唤醒线程B,并且只会唤醒B 因为唤醒的是头结点的下一个节点 ,但不意味着线程B一定会抢到锁,此时线程B还会一直自旋 因为非公平性会导致另一个线程D 半路杀出插队抢到锁
完整的图示
![](https://i-blog.csdnimg.cn/blog_migrate/fc38a8c51faead1e9ab7720ec8a60d48.png)
源码分析
![](https://i-blog.csdnimg.cn/blog_migrate/e8066d1b1711dad3362752c9b792a95c.png)
公平锁 非公平锁
加锁
final void lock() { 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 ) { 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 ; } } |
final void lock() { if (compareAndSetState( 0 , 1 )) setExclusiveOwnerThread(Thread.currentThread()); else acquire( 1 ); } public final void acquire( int arg) { if (!tryAcquire(arg) && //没有抢到锁 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); } protected final boolean tryAcquire( int acquires) { return nonfairTryAcquire(acquires); } 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 ; } |
分别分析 抢到锁的逻辑代码 没有抢到锁的逻辑代码
没有抢到锁则加入队列,并进行自旋等待
public final void acquire( int arg) { if (!tryAcquire(arg) && //没有抢到锁 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) //1,addWaiter()添加一个互斥锁的节点构建双向链表 2,acquireQueued()自旋锁和阻塞的操作 selfInterrupt(); } |
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
private 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; if (pred != null ) { node.prev = pred; if (compareAndSetTail(pred, node)) { pred.next = node; return node; } } enq(node); return node; } private Node enq( final Node node) { for (;;) { Node t = tail; if (t == null ) { // Must initialize if (compareAndSetHead( new Node())) tail = head; } else { node.prev = t; if (compareAndSetTail(t, node)) { t.next = node; return t; } } } } |
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
final boolean acquireQueued( final Node node, int arg) { boolean failed = true ; try { boolean interrupted = false ; //自旋 for (;;) { //1,begin ----- 尝试获得锁 final Node p = node.predecessor(); if (p == head && tryAcquire(arg)) { //下面代码2处没有抢到锁会被阻塞挂起,唤醒后返回interrupted = true ,接着活继续自旋for(;;)抢占锁tryAcquire(arg) 抢到锁则将当前节点置为头结点 删除原来的头节点并进行回收 setHead(node); p.next = null ; // help GC failed = false ; return interrupted; } //end ------ //2,没有抢占到锁 则阻塞 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(); } |
static final class Node { /** Marker to indicate a node is waiting in shared mode */ static final Node SHARED = new Node(); /** Marker to indicate a node is waiting in exclusive mode */ static final Node EXCLUSIVE = null ; /** waitStatus value to indicate thread has cancelled */ static final int CANCELLED = 1 ; /** waitStatus value to indicate successor's thread needs unparking */ static final int SIGNAL = - 1 ; /** waitStatus value to indicate thread is waiting on condition */ static final int CONDITION = - 2 ; /** * waitStatus value to indicate the next acquireShared should * unconditionally propagate */ static final int PROPAGATE = - 3 ; volatile int waitStatus; |
释放锁
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 ; //从tail--head遍历 因为构建双向链表的时候是 构建双向链表的过程pre next关系指向是不安全的不连续的 且 先构建的是pre关系 for (Node t = tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0 ) s = t; } if (s != null ) LockSupport.unpark(s.thread); } |