concurrent-4-AQS-ReentrantLock-Lock
来源:互联网 发布:excel 删除重复数据 编辑:程序博客网 时间:2024/05/22 03:18
可重入锁源码解析。
AbstractQueuedSynchronizer#Node 节点信息
tatic 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; ////因为超时或者中断,node会被设置成取消状态,被取消的节点时不会参与到竞争中的,会一直保持取消状态不会转变为其他状态; /** 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; //该状态表示下一次节点如果是Shared的,则无条件获取锁。 volatile int waitStatus; //节点的状态值 volatile Node prev; //前节点 volatile Node next; //后节点 volatile Thread thread; //节点关联线程 Node nextWaiter; //连接到下一个节点等待条件,或特殊值共享
lock获取资源
ReenTrantLock#lock
//加锁 public void lock() { sync.lock(); //实际为封装AQS实现类 }
ReenTrantLock#NonfairSync#lock
final void lock() { if (compareAndSetState(0, 1)) //尝试cas操作,抢占锁 setExclusiveOwnerThread(Thread.currentThread()); //标记独占锁为被当前线程 else acquire(1); //尝试获取锁(AQS方法) }
AbstractQueuedSynchronizer#acquire
public final void acquire(int arg) { if (!tryAcquire(arg) && //尝试直接去获取资源,如果成功则直接返回 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) //addWaiter:线程加入等待队列的尾部,并标记为独占模式 //acquireQueued 尝试获取资源,如果获取了资源被且没有被标记为中断则返回false,否则返回true selfInterrupt(); //等待中标记中断,获取资源后自我中断 }
ReenTrantLock#NonfairSync#tryAcquire
protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); //非公平锁的获取资源方式 }
ReenTrantLock#NonfairSync#nonfairTryAcquire
final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); //获取状态 if (c == 0) { //如果是0,则尝试cas操作加锁,无须进入队列排队,可能被其它线程抢占 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; }
AbstractQueuedSynchronizer#addWaiter
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) { //如果pred 不为null 则非初始化状态 尝试cas操作,失败则enq进行循环cas操作 node.prev = pred; if (compareAndSetTail(pred, node)) { //尝试入队列 pred.next = node; return node; } } enq(node); //循环cas入sync队列 return node; }
AbstractQueuedSynchronizer#enq
private Node enq(final Node node) { for (;;) { Node t = tail; //指定 t 为 尾部节点 if (t == null) { // Must initialize //初始化 if (compareAndSetHead(new Node())) //将head位设置为新节点 tail = head; } else { node.prev = t; //将node 节点的prev 标记为 tail节点(可能有其它线程在重复改变tail) if (compareAndSetTail(t, node)) { //如果cas操作成功,那么将node节点标记为tail节点 t.next = node; //同时将t(上一次的tail节点)的下一个节点标记为node(新的tail节点) return t; } } } }
AbstractQueuedSynchronizer#acquireQueued
final boolean acquireQueued(final Node node, int arg) { boolean failed = true; //标记是否成功获取资源 try { boolean interrupted = false; //标记是否被中断 for (;;) { final Node p = node.predecessor(); //获取前节点 if (p == head && tryAcquire(arg)) { //如果前节点是head,则尝试获取资源!!!!!队列中头部节点先获取资源 setHead(node); //获取成功,将本节点设置为head节点 p.next = null; // help GC failed = false; return interrupted; //成功获取资源并且未被中断 } //shouldParkAfterFailedAcquire:判断在获取资源失败后,是否应该睡眠(根据前节点的waitStatus)。 //parkAndCheckInterrupt:睡眠的同时,判断是否有中断状态 if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed) cancelAcquire(node); //如果失败则取消获取资源 } }
AbstractQueuedSynchronizer#shouldParkAfterFailedAcquire
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) { int ws = pred.waitStatus; //下一个节点的等待状态 if (ws == Node.SIGNAL) //signal 状态则正常放回 /* * This node has already set status asking a release * to signal it, so it can safely park. */ return true; if (ws > 0) { /* * Predecessor was cancelled. Skip over predecessors and * indicate retry. */ do { //如要将所有>0 即取消的节点都排除 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. */ //cas 操作将节点的waitStatus标记为signal状态 compareAndSetWaitStatus(pred, ws, Node.SIGNAL); } return false; }
UnLock
ReenTrantLock#unLock
public void unlock() { sync.release(1); //释放资源 }
AbstractQueuedSynchronizer#release
public final boolean release(int arg) { if (tryRelease(arg)) { //尝试释放锁成功(可能重入了多次锁) Node h = head; //如果没有队列外的线程获取锁,那么获取锁资源的一定是队列头,此处需要唤醒其它线程 //从队尾开始唤醒,因为队尾可能一直会新加入线程,双端队列容易死循环 if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; }
ReenTrantLock#tryRelease
protected final boolean tryRelease(int releases) { int c = getState() - releases; //获取当前线程状态值 if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { //如果线程状态为0,则表示已经释放了锁 free = true; setExclusiveOwnerThread(null); } setState(c); //设置状态 return free; }
AbstractQueuedSynchronizer#unparkSuccessor
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) 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; //如果下一个节点为null,或者状态为取消 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); }
阅读全文
0 0
- concurrent-4-AQS-ReentrantLock-Lock
- Java Concurrent Lock ReentrantLock简介
- 解析Concurrent包下的ReentrantLock、LockSupport、AQS
- AQS(5):ReentrantLock
- ReentrantLock及AQS浅谈
- AQS 和 reentrantlock
- concurrent-5-AQS-Condition
- concurrent-5-AQS-ReentrantReadWriteLock
- concurrent-6-AQS-Semaphore
- java.util.concurrent(JUC)的研究--》锁机制--》Lock与ReentrantLock
- 使用Lock concurrent包当中ReentrantLock 可以实现synchronized 一样的效果
- java concurrent之ReentrantLock
- java.util.concurrent.ReentrantLock
- concurrent包之reentrantlock
- Concurrent包中的AQS理解
- concurrent-7-AQS-CountDownLatch,CyclicBarrier
- 分析ReentrantLock之lock
- 显式锁Lock、ReentrantLock
- 编程语言概览
- IE9下不打开F12调试工具无法打开页面的问题解决
- C语言的函数
- [COGS2652]秘术「天文密葬法」-长链剖分-01分数规划
- (Spring框架)单例和多例以及依赖注入
- concurrent-4-AQS-ReentrantLock-Lock
- JSON.stringify和JSON.parse
- C、C++之动态数组的实现二(C++版本)
- PHP获取汉字首字母并分组排序
- 从此折腾有了生命
- 第一行代码笔记 Activity
- ubuntu16.04和windows10双系统下,ubuntu根目录扩容方法
- 【二】CentOS7安装postgresql并配置远程连接
- android 华为手机导航栏适配