首页 > 编程语言 >ReentrantLock源码笔记 - 释放锁(JDK 1.8)

ReentrantLock源码笔记 - 释放锁(JDK 1.8)

时间:2023-11-07 14:46:20浏览次数:41  
标签:node 释放 JDK ReentrantLock 后继 源码 null 节点

ReentrantLock源码学习 - 释放锁(unlock)


上次谈到了利用ReentrantLock的非公平和公平加锁方式,那么接下来看看释放锁的流程

首先调用ReentrantLock的unlock方法

public void unlock() {
    sync.release(1);
}

然后会调用AbstractQueuedSynchronizer(AQS)的release方法,在这个方法中首先会调用ReentrantLock的Sync的tryRelease方法,来进行尝试释放锁,如果返回true,那么获取CLH队列的头结点,判断头结点不为空并且头结点的状态不为0(None),那么就调用AQS的unparkSuccessor方法。

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方法里,首先让当前的state与传入的值(这里为1)进行相减,然后得到c,判断当前线程是不是获取独占锁的线程,如果不是,直接抛出异常;如果是,那么需要判断c是否为0,因为只有c为0时,才符合释放独占锁的条件,这是设置独占锁线程为null,最后设置下state的值(注意这里c为0不为0都会设置)

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

接下来来看方法unparkSuccessor,该方法的作用就是为了释放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;
    if (ws < 0)
        compareAndSetWaitStatus(node, ws, 0); // 利用CAS 将状态设置为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;
    // 判断后继节点是否为空 或者 后者后继节点的状态为CANCELLED
    if (s == null || s.waitStatus > 0) {
        s = null; // 将后继节点置为null
        // 从尾节点从后向前开始遍历知道节点为空或者当前节点为止
        for (Node t = tail; t != null && t != node; t = t.prev)
            if (t.waitStatus <= 0) // 如果此时节点的状态小于等于0
                s = t; // 将此节点赋给传入节点的后继节点
    }
    if (s != null)  // 节点不为空,释放
        LockSupport.unpark(s.thread);
}

参考:

http://blog.csdn.net/luonanqin/article/details/41871909


title: ReentrantLock源码笔记 - 释放锁(JDK 1.8)
categories: [Java, JUC]
tags: [java, Lock, JUC, ReentrantLock]
author: Mingshan
date: 2017-11-12

标签:node,释放,JDK,ReentrantLock,后继,源码,null,节点
From: https://www.cnblogs.com/mingshan/p/17793606.html

相关文章

  • 直播带货源码,android editText设置颜文字过滤
    直播带货源码,androideditText设置颜文字过滤 //给editText设置过滤器  InputFilterinputFilter=newInputFilter(){    //限制输入表情    Patternemoji=Pattern.compile("[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27f......
  • 在线直播源码,js 文件上传 图片上传 传输速度计算
    在线直播源码,js文件上传图片上传传输速度计算<!doctypehtml><html><head>  <metacharset="UTF-8">  <metaname="viewport"content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scal......
  • 在线直播系统源码,输入框限制字节数 区分中英文
    在线直播系统源码,输入框限制字节数区分中英文   // 规则名称验证规则  不包含特殊字符   letcheckGroupName=(rule,value,callback)=>{    letreg=/^[0-9A-Za-z\u4e00-\u9fa5\(\)\(\)]+$/;     if(value!==''&&!reg.test(value)){......
  • zookeeper源码(04)leader选举流程
    在"zookeeper源码(03)集群启动流程"中介绍了leader选举的入口,本文将详细分析leader选举组件和流程。leader选举流程(重要)quorumPeer的start阶段使用startLeaderElection()方法启动选举LOOKING状态,投自己一票createElectionAlgorithm-创建选举核心组件:QuorumCnxManager(管......
  • Spring Boot 2.x版本 + JDK17使用虚拟线程
    来源:https://spring.io/blog/2022/10/11/embracing-virtual-threadsconfig里定义两个类:@ConfigurationpublicclassThreadConfig{@Bean(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME)publicAsyncTaskExecutorasyncTaskExecutor(){......
  • Java:SpringBoot实现JDK动态代理和CGLIB动态代理
    (目录)需要代理的对象//接口publicinterfacePayService{voidpay();}//实现publicclassAliPayServiceimplementsPayService{@Overridepublicvoidpay(){System.out.println("AliPayService");}}1.JDK动态代理在JDK动态代......
  • eclipse中maven依赖的jar源码中文注释乱码解决
    通过maven下载源代码,在eclipse中浏览源代码时,发现中文注释为乱码的问题。eclipse默认编码造成的问题。可以通过以下方法解决:1.修改Eclipse中文本文件的默认编码:windows->Preferences->general->Workspace->Textfileencoding设置为UTF-82.修改JAVA源文件的默认编码:windows->P......
  • JDK 21安装及环境配置
    注意:1、本文的性质为初学者的实操记录,文中内容若与你遭遇的情况不符,请另行寻找更靠谱的教程。比如我参考的就是:“AAA黄豆AAA”的JDK21安装教程2、本文撰写时间为2023年11月6日,操作系统为Windows10家庭版,若时殊事异,请理性对待。一、安装JDK211、从Oracle官网获取JDK21安......
  • 智慧校园管理平台源码,智慧校园小程序源码,智慧校园电子班牌系统源码
     智慧校园是指以物联网、云计算、大数据分析等新技术为核心技术,提供智慧化、数据化、网络化、协作一体化的教学、科研、管理和生活等各类服务,促进信息技术与教育教学有效深度融合,提高学生学习效果,最终实现智慧化教学和管理的校园模式。1、数字教学,教师直接通过APP教学平台布置作......
  • Linux Centos安装JDK1.8教程
    第一步:先下载JDK1.8,可以去官网下载,也可以直接这里的:下载地址:链接:https://pan.baidu.com/s/1f1EDWvG-GzpQRJaC_W4SpA密码:9pj1先检查是否有安装JDK:#rpm-qa|grepjdk先把系统自带的干掉(如果没有直接跳过):   rpm-e--nodepsjava-1.7.0-openjdk-1.7.0.45-2.4.3.3.el6.x86_64......