ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

AQS源码阅读

2022-06-04 20:01:30  阅读:165  来源: 互联网

标签:node Node return AQS int 源码 阅读 arg final


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;
    }

 

标签:node,Node,return,AQS,int,源码,阅读,arg,final
来源: https://www.cnblogs.com/LLFA/p/16339014.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有