AQS是用来构建锁或者其它同步器组件的重量级基础框架及整个JUC体系的基石,通过内置的FIFO队列来完成资源获取线程的排队工作,并通过一个int类变量
表示持有锁的状态。
我将以reentrantlock为切入点,阅读ASQ源码。
注:reentrantlock默认是线程不安全的,当然也可以设置为线程安全。
一、lock.lock();
final void lock() {
//通过CAS尝试加锁,当获到独占锁时,status=1, if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else //尝试获取锁
acquire(1); }
public final void acquire(int arg) { //arg = 1 if (!tryAcquire(arg) && //这里用到了模板设计模式 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
tryAcquire()
final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); //0 if (c == 0) { if (compareAndSetState(0, acquires)) {//尝试获取锁,获取成功返回true 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;//没抢到独占锁,返回false }
当尝试获取锁失败时,需要加入等待队列,但加入等队列的时候,还会进行对独占锁的抢占。
先加入等待addWaiter(Node.EXCLUSIVE);(EXCLUSIVE为null)
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; }
acquareQueue()
final boolean acquireQueued(final Node node, int arg) { //node = t, arg = 1 boolean Failed = true; try { boolean interrupted = false; for (;;) { final Node p = node.predecessor();
//头结点,并尝试获取锁(首次抢占的节点前的节点为空节点) if (p == head && tryAcquire(arg)) { setHead(node); p.next = null; // help GC Failed = false; return interrupted; }
if (shouldParkAfterFailedAcquire(p, node) && //p(哨兵节点)waitstatus设置为SIGNAL (-1) parkAndCheckInterrupt()) interrupted = true; } } finally { if (Failed) cancelAcquire(node); //将t节点的等待状态设置为1 } }
除了首个进入队列的节点的waitstatus=1,后续加入的节点都为0,且不会抢夺独占锁
解锁lock.unlock
public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。