独占式锁acquire源码注释

AQS,即AbstractQueuedSynchronizer, 队列同步器,它是Java并发用来构建锁和其他同步组件的基础框架。

args代表的含义:
		//独占式 args为null
      static final Node EXCLUSIVE = null;
       // 当前节点从同步队列中取消 
       static final int CANCELLED =  1;
       //后继节点的线程处于等待状态,如果当前节点释放同步状态
       会通知后继节点,使得后继 节点的线程继续运行。 
       static final int SIGNAL    = -1;
      //节点在等待队列中,节点线程等待在Condition上,当其他线程对Condition调用了 signal()方法后,该节点将会从等待队列中转移到同步队列中,加入到对同步状态的获取中
       static final int CONDITION = -2;
      //表示下一次共享式同步状态获取将会无条件地被传播下去
       static final int PROPAGATE = -3;

AbstractQueuedSynchronizer

public abstract class AbstractQueuedSynchronizer
    extends AbstractOwnableSynchronizer
    implements java.io.Serializable {
    ......
    }

获取锁过程:

public final void acquire(int arg) {
		//如果tryAcquire()不成功且
		//acquireQueued(addWaiter(Node.EXCLUSIVE),arg)成功
		//会调用selfInterrupt()方法
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

下面我们进入if判断中的饿方法具体看一下获取锁的具体流程

//如果tryAcquire()方法传入参数不符合要求,会直接抛出异常
//如果成功获取到锁,返回true,否则返回false
    protected boolean tryAcquire(int arg) {
        throw new UnsupportedOperationException();
    }

addwaiter()方法,将未竞争到锁的线程包装成节点放入同步队列末端

/**
     * Creates and enqueues node for current thread and given mode.
     *
     * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
     * @return the new node
     */
    private Node addWaiter(Node mode) {
    //将未竞争到锁的线程包装成节点,并标记清楚模式:
    //是EXCLUSIVE(独占式)还是SHARED(共享式)
        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指向双向链表的最后一个节点
            node.prev = pred;
            //使用CAS将node入队
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        //如果CAS入队失败,调用enq()方法进行入队操作
        enq(node);
        return node;
    }

enq()方法,如果未将node节点入队,则一直自旋进行CAS入队操作

/**
     * Inserts node into queue, initializing if necessary. 
     * See picture above.
     * @param node the node to insert
     * @return node's predecessor
     */
    private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            //如果尾节点为空,说明同步队列此时为空队列
            if (t == null) { // Must initialize
            	//新建一个头结点,作为同步队列的头结点
                if (compareAndSetHead(new Node()))
                	//将使尾结点指向新创建的头结点
                    tail = head;
            } else {
            	//如果尾节点不为空,说明同步队列现在有等待节点
            	//node节点的前驱指针指向尾节点
                node.prev = t;
                //使用CAS将node尾插入同步队列
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;
                }
            }
        }
    }

acquireQueued(final Node node, int arg){ }//请求队列

/**
     * Acquires in exclusive uninterruptible mode for thread already in
     * queue. Used by condition wait methods as well as acquire.
     *
     * @param node the node
     * @param arg the acquire argument
     * @return {@code true} if interrupted while waiting
     */
    final boolean acquireQueued(final Node node, int arg) {
    	//设置失败标志true
        boolean failed = true;
        try {
        	//是否被interrupted标志 设置为false
            boolean interrupted = false;
            for (;;) {
            	//因为在死循环中,所以相当于在从后向前遍历同步队列
                final Node p = node.predecessor();
                //如果p节点尾头结点,且获取锁成功
                if (p == head && tryAcquire(arg)) {
                	//设置node节点尾头结点
                	//p节点赋为Head,thread赋为null,p.prev赋为null
                	//相当于将p节点从同步队列中删除
                    setHead(node);
                    p.next = null; // help GC
                    //failed标志位赋为false,双重否定表肯定,
                    //意思大概为:距离头结点最近的合法节点获取锁成功并被出队
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

shouldParkAfterFailedAcquire(Node pred, Node node)
单步目的:是尝试将前驱节点改为SIGNAL,表示此时当前节点应该被阻塞

放在循环中的语义:一直在acquireQueued()方法中自旋,直到将前驱节点状态置为SIGNAL,表示此时应当将当前节点阻塞

private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        int ws = pred.waitStatus;
        if (ws == Node.SIGNAL)//singal == -1
            /*
             * This node has already set status asking a release
             * to signal it, so it can safely park.
             */
            return true;
        if (ws > 0) {//cancelled,取消状态
            /*
             * Predecessor was cancelled. Skip over predecessors and
             * indicate retry.
             */
             //从后往前,寻找节点状态小于0的节点,即可以被park的节点
            do {
                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.
             */
             //如果该节点的状态小于等于0,设置该节点状态为SIGNAL,
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
        }
        //返回false,与&& 后的方法一起决定  是否    会阻塞当前线程
        return false;
    }

parkAndCheckInterrupt()
前驱节点状态置为SINGAL后,将当前节点线程阻塞
放在循环中,语义为将shouldParkAfterFailedAcquire()中节点置为SINGAL
的线程节点阻塞

    /**
     * Convenience method to park and then check if interrupted
     *
     * @return {@code true} if interrupted
     */
    private final boolean parkAndCheckInterrupt() {
    	//阻塞节点线程
        LockSupport.park(this);
        return Thread.interrupted();
    }

独占式锁的释放: 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;
    }

tryRelease

    protected boolean tryRelease(int arg) {
        throw new UnsupportedOperationException();
    }

unparkSuccessor()//唤醒距离头结点最近的非空节点

   /**
     * Wakes up node's successor, if one exists.
     *
     * @param node the node
     */
    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;
       //CAS将头结点=状态置为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;
        }
        if (s != null)
            LockSupport.unpark(s.thread);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值