ReentrantLock源码之二unlock方法解析(锁的释放)

21 篇文章 0 订阅
前面一节 中,我们分析了ReentrantLock.lock()方法,接下来我们接着分析ReentrantLock.unlock()方法。

1.ReentrantLock.unlock()分析

(1)首先尝试释放锁,如果要求释放数等于锁状态数,那么将锁状态位清0,清除锁所有者,返回true;否则返回false;
(2)如果(1)返回的是true,说明锁完全释放。接下来将检查等待队列,并选择下一个节点恢复(该节点必须是waitStatus),

如果该节点不存在或者被取消,则选择从尾节点开始,选取最靠近头节点的等待节点,同时清理队列中线程被取消的节点;

大家回忆下lock()实现机制,新节点是从尾部插入的。这就说明AQS里面的 CLH其实是一个FIFO队列(用双链表实现的FIFO队列).

(3)如果(1)返回false,说明锁只是部分释放,当前线程仍旧持有该锁;

 1 java.util.concurrent.locks.ReentrantLock
 2   public  void unlock()  {
 3        sync.release(1);
 4 }

 5
 6 java.util.concurrent.locks.AbstractQueuedSynchronizer
 7 public  final  boolean release( int arg)  {
 8        if (tryRelease(arg)) {   
 9            Node h = head;
10            if (h != null && h.waitStatus != 0)
11                unparkSuccessor(h);
12            return true;
13        }

14        return false;
15    }

16
17
18   protected  final  boolean tryRelease( int releases)  {
19            int c = getState() - releases;   //重入锁加锁的次数-释放数量
20            if (Thread.currentThread() != getExclusiveOwnerThread())   //判断独占锁是否为当前线程所有
21                throw new IllegalMonitorStateException();
22            boolean free = false;
23            if (c == 0) {       //加锁次数=释放数量
24                free = true;
25                setExclusiveOwnerThread(null);     //清除锁拥有者标识
26            }

27            setState(c);        //设置加锁状态
28            return free;
29        }

30
31
32   /**
33     * Wakes up node's successor, if one exists.
34     *
35     * @param node the node
36     */

37      private  void unparkSuccessor(Node node)  {
38        /*
39         * Try to clear status in anticipation of signalling.  It is
40         * OK if this fails or if status is changed by waiting thread.
41         */

42        compareAndSetWaitStatus(node, Node.SIGNAL, 0);    //清除头节点signal状态
43
44        /*
45         * Thread to unpark is held in successor, which is normally
46         * just the next node.  But if cancelled or apparently null,
47         * traverse backwards from tail to find the actual
48         * non-cancelled successor.
49         */

50        Node s = node.next;
51        if (s == null || s.waitStatus > 0) {    //等待队列唤醒的竞争满足FIFO,本段代码主要是寻找最靠近头节点的,且waitStatus为signal、condition的链表节点
52            s = null;
53            for (Node t = tail; t != null && t != node; t = t.prev)
54                if (t.waitStatus <= 0)
55                    s = t;
56        }

57        if (s != null)
58            LockSupport.unpark(s.thread);
59    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值