前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ReentrantLock中的unlock流程

ReentrantLock中的unlock流程

作者头像
None_Ling
发布2018-10-24 14:48:36
5750
发布2018-10-24 14:48:36
举报
文章被收录于专栏:Android相关Android相关

在调用到ReentrantLock的unlock方法的时候,无论公平锁与非公平锁都会调用到sync.release(1)方法。

Sync.release方法解析

该方法注释为

代码语言:javascript
复制
/**
 * Releases in exclusive mode.  Implemented by unblocking one or
 * more threads if {@link #tryRelease} returns true.
 * This method can be used to implement method {@link Lock#unlock}.
 *
 * @param arg the release argument.  This value is conveyed to
 *        {@link #tryRelease} but is otherwise uninterpreted and
 *        can represent anything you like.
 * @return the value returned from {@link #tryRelease}
 */

从一个独占的模式中退出。如果tryRelease方法返回true的话,则通过unblock一个或者多个线程来实现。这个方法通常用来实现Lock.unlock函数。

而代码如下

代码语言:javascript
复制
 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方法,如果返回true的话,说明解锁成功,那么则会将当前的head节点进行解锁,接着判断waitStatus不为0,说明当前头节点处于非运行状态,则会调用unparkSuccessor,将头节点传入,而头节点的Thread也因此被唤醒。

tryRelease方法解析

代码语言:javascript
复制
protected final boolean tryRelease(int releases) {
        int c = getState() - releases;
        if (Thread.currentThread() != getExclusiveOwnerThread())
            throw new IllegalMonitorStateException();
        boolean free = false;
        if (c == 0) {
            free = true;
            setExclusiveOwnerThread(null);
        }
        setState(c);
        return free;
    }
  1. 判断当前的线程是否是占用锁的线程,如果不是的话,那么抛出非法异常
  2. 否则的话,则判断减少releases之后的值是否为0,如果为0的话,说明目前锁都已经被释放了,则free标识为true,说明当前锁处于空闲状态,并且将当前锁占有线程置空
  3. 设置当前的锁状态,并且返回当前锁是否是空闲的

unparkSuccessor解析

该方法的作用是唤醒一个这个节点的后继,也就是head->next。

代码语言:javascript
复制
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;
    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);
}
  1. 首先判断当前节点的waitStatus是否小于0,如果小于0的话,说明当前的状态都是SINGNAL等状态,则通过CAS操作将当前节点的ws变量清空
  2. 获取当前节点的next节点,如果next节点为空或者waitStatus大于0的话,那么说明next节点不合法,则会从后往前遍历,找到最前面一个waitStatus<=0的节点,只有这种节点的线程代表着被阻塞了,那么则调用LockSupport.unpark(s.thread)将该节点阻塞的线程释放,继续执行。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016.07.08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Sync.release方法解析
  • tryRelease方法解析
  • unparkSuccessor解析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档