文章目录

  • 1 想要读懂这篇文章必须要拥有的前置知识
  • 2 想写这篇文章的原因
  • 3 困扰我很久的Reentrantlock源代码1 --- 貌似无用的变量failed
  • 4 困扰我很久的Reentrantlock源代码2 --- unpark后为啥要来个Thread.interrupted();
  • 5 小记

源码地址:https://github.com/nieandsun/concurrent-study.git


1 想要读懂这篇文章必须要拥有的前置知识

《【并发编程】 — synchronized/ReentrantLock两大特性(可重入性和不可中断性)介绍》
《【并发编程】— interrupt、interrupted和isInterrupted使用详解》
《【并发编程】 — Reentrantlock源码解析2:公平锁加锁过程超详细解析》
《【并发编程】 — Reentrantlock源码解析3:公平锁释放锁过程超详细解析》


2 想写这篇文章的原因

下面这幅图是我在文章《【并发编程】 — Reentrantlock源码解析3:公平锁释放锁过程超详细解析》中给出的一幅图。

不知道大家对这幅图中的代码有没有疑惑??? —> 说实话我有,而且困扰了我很久很久!!!
本篇文章将主要针对我困扰的问题进行讨论,并给出我自认为可以自圆其说的解释!!!


3 困扰我很久的Reentrantlock源代码1 — 貌似无用的变量failed

我们先来看一下1中红色标号为5的代码。

我的疑问如下:

可能有人会说:

在try那块代码里 failed = false;这句代码之前有可能会抛出异常,如果抛了异常之后就会走finally代码块,那个时候failed还是初始值true ,那这个逻辑就有意义了。 —> 这句话说的一点没错,但是这是一种怎样的情况呢???

假如你恰巧看过这篇文章《【并发编程】 — synchronized/ReentrantLock两大特性(可重入性和不可中断性)介绍》,那我觉得你应该是可以回答上来的:

使用Reentrantlock锁,当某个线程正在被park时,使用stop方法中断此线程,就正好是这种情况。


相信大家都知道使用stop方法中断某个线程,会直接释放掉本线程所持有的所有资源,举个简单的栗子来说,假如我们正在使用某个线程下载电影,如果该线程通过stop进行中断,则原来下载的内容将全部丢失,因此可以简单将其理解为“暴力中断”(自己发明的词,见笑☺),只要调用了,就不可能恢复了 —》 应该正是基于这个原因,JDK官方将其@Deprecated了。

但是万一有些业务确实就需要这种“暴力中断”呢???

看过 《【并发编程】 — synchronized/ReentrantLock两大特性(可重入性和不可中断性)介绍》这篇文章的应该知道,

synchronized关键字的处理逻辑是,假如线程被park了,即使使用stop进行“暴力中断”, 对不起, 没法给你立即中断 —》 但是当你有了抢锁资格后,就立即给你中断!!!

仔细想想这个逻辑 ,是不是一个挺操蛋的逻辑??? 我都采用暴力中断了,你还不给我立即中断,而当我有抢锁资格了,我肯定这时候就大概率不想中断了啊,你到立刻给我来个暴力中断!!!

或许Doug Lea大神也觉得这个逻辑比较操蛋吧。。。所以人家在Reentrantlock中做了改进!!!

要很详整的说出来具体的改进应该还要把cancelAcquire的源码给搬出来,但是这里我不打算搬出来了,所以只是简单的,从比较宏观的角度去阐述一下(当然私底下,我已经打过n遍断点验证过我的观点了,有兴趣的可以自己亲自动手试试!!!)。


假设Node链表中有t2和t3在排队等着抢锁,其结构如下,这时候突然想用stop()方法“暴力中断”t2线程。

在不看源码的情况下,我觉得你仔细想想应该也能想出个一二来。 首先我们应该知道既然t2要被“暴力中断”了,那这个线程说的直白点就直接相当于没有了。。。 那该线程在Node链表里肯定也就没必要存在了吧; —》 反过来想,假若我不处理Node链表,在解锁时发现Node链表里竟然除了head外还有一个线程为null的Node,你是不是感觉也很不可理解??? —> 想到这里其实你就知道Doug Lea大神会干什么了 —》 没错,将被stop的线程从Node链表里出队。

以上图而言Doug Lea大神的逻辑基本如下:

  • (1)既然stop了,线程会被暴力中断,但是因为有finally关键字,所以会进入到cancelAcquire()方法
  • (2)将线程t2对应的节点的waitStatus置为1
  • (3)unpark线程t3 ,让线程t3去自旋 —》 由文章《【并发编程】 — Reentrantlock源码解析2:公平锁加锁过程超详细解析》可知,由于线程t2所在Node的waitStatus此时为1,因此会在t3自旋时,将其从Node链表中给踢出去 —》 由此便完成了被stop的线程t2所在节点的出队。

4 困扰我很久的Reentrantlock源代码2 — unpark后为啥要来个Thread.interrupted();

这块代码真是困扰了很久很久很久!!!! - > 甚至都有时候都怀疑自己太钻死牛角尖了!!!

昨天非常有幸,在B站看到了子路老师的讲解,后又思考良久,甚至找子路老师聊了该问题,终于找到了一个可以自圆其说的原因!!!


如果看懂了我这篇文章《【并发编程】— interrupt、interrupted和isInterrupted使用详解》再看上面这张图,你脑子要TMD崩溃!!!

为啥这样说呢???

我们这里直接看线程t被打断的情况,他做了个啥啊,这是!!! —》 先判断一下是否被打断(这里要注意一下interrupted和isInterrupted的区别,但是对于这里不重要!!!) —》如果是 —》我再打断一次

  • 而我想大家应该都知道使用interrupt做打断,其实就相当于皇帝在某个妃子房间里玩耍,突然某个太监在外面喊:万岁,注意龙体,该去休息了。---》 但是皇帝到底停不停,全由它自己说了算!!!
  • 那TMD就让人疑惑了,Doug Lea这是要干啥啊,闲的蛋疼?在中间传个话???
  • 如果它啥事不做,不也是这样么???—》 也就是说上面的流程不是和下面的流程一个样么???— 而且下面是不是效率还更高一些???


那Doug Lea为啥要这样搞呢???


研究了n天后,结合子路老师的解答,我给出的答案是为了代码格式的统一,以及某些锁少写几行重复代码!!!

首先来看一下用到parkAndCheckInterrupt() 这个方法的所有方法:

  • acquireQueued方法 — 独占锁自旋主要逻辑
  • doAcquireInterruptibly方法 — 可打断的独占锁自旋主要逻辑
  • doAcquireShared方法 — 共享锁自旋主要逻辑
  • doAcquireSharedInterruptibly方法— 可打断的共享锁自旋主要逻辑

这算不算格式上的统一??? —》 有兴趣的可以留言交流!!!


其次来简单看一下acquireQueueddoAcquireInterruptibly两个方法的简单比较:

这算不算在某些锁少写几行重复代码 —》 有兴趣的可以留言交流!!!


5 小记

有时候感觉自己像个傻子!!! 总习惯于沿着一个方向不停的钻钻钻!!!
上学时老师说我适合搞研究,能做事, 但又不适合,做的太多,研究的太深, 但是却总不发文章。
于是思考了将近半年,下定决心要去工作,所幸手头的工作都比较简单 。

因此想快速搭建起自己的知识体系,但是发现自己还是会时不时的钻钻钻!!!—》于是学的东西慢且少,而且越学越觉得不懂的越多!!! —》 所以¥¥¥ 。。。

唉!!!唉!!!唉!!!


end!!!

【并发编程】 --- Reentrantlock源码解析5:再探不可中断性 + 线程unpark后诡异的Thread.interrupted()判断相关推荐

  1. 并发编程与源码解析 (三)

    并发编程 (三) 1 Fork/Join分解合并框架 1.1 什么是fork/join ​ Fork/Join框架是JDK1.7提供的一个用于并行执行任务的框架,开发者可以在不去了解如Thread.R ...

  2. Java并发编程-ReentrantLock源码分析

    一.前言 在分析了 AbstractQueuedSynchronier 源码后,接着分析ReentrantLock源码,其实在 AbstractQueuedSynchronizer 的分析中,已经提到 ...

  3. Java并发编程 ReentrantLock 源码分析

    ReentrantLock 一个可重入的互斥锁 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大. 这个类主要基于AQS(Abst ...

  4. 并发编程---ConcurrentHashMap源码解析

    2019独角兽企业重金招聘Python工程师标准>>> ConcurrentHashMap是java中为了解决HashMap不能支持高并发而设计的新的实现. ConcurrentHa ...

  5. synchronized 和 reentrantlock 区别是什么_JUC源码系列之ReentrantLock源码解析

    目录 ReentrantLock 简介 ReentrantLock 使用示例 ReentrantLock 与 synchronized 的区别 ReentrantLock 实现原理 Reentrant ...

  6. 多线程(三)之ReentrantLock源码解析

    2019独角兽企业重金招聘Python工程师标准>>> 今天分析ReentrantLock类的源码,在看源码之前,先学习AQS(AbstractQueuedSynchronizer) ...

  7. 面试官系统精讲Java源码及大厂真题 - 32 ReentrantLock 源码解析

    32 ReentrantLock 源码解析 才能一旦让懒惰支配,它就一无可为. 引导语 上两小节我们学习了 AQS,本章我们就要来学习一下第一个 AQS 的实现类:ReentrantLock,看看其底 ...

  8. Java并发编程-AQS源码之条件队列

    System.out.println(name + "==>成功获取到锁" + lock); try { condition.await(); } catch (Interr ...

  9. 【java】java 并发编程 Condition 源码分析

    文章目录 1.概述 1.2 案例 3.2 实现方法顺序调用 2.源码解析 2.1 接口方法 2.2 继承 2.3 队列 2.4 await 分析 2.4.1 线程1 await 2.4.2 线程2 a ...

最新文章

  1. 计算器是如何计算sin、cos等科学函数的值呢?
  2. 加密解密、Openssl、自建CA
  3. Bootstrap~大叔封装的弹层
  4. access 战地1不加入ea_炒牛肉时,想要牛肉嫩滑又不老,只需加入1样东西,很多人都不懂...
  5. xsl调用java方法传参_Java中的XSL转换:一种简单的方法
  6. 个人支付源码_[5G时代投资风口源码修复版] 投资区块链+订制UI完美版+对接免签支付+自带发圈推广任务奖励+视频教程...
  7. flask第二十篇——模板【3】
  8. idea git和svn间切换
  9. 对象图(Object Diagram)
  10. 台式计算机如何联络无线网,台式电脑怎么无线上网
  11. Java-热插拔技术
  12. linux更新war包操作步骤,关于Linux系统下基于Tomcat部署和升级war包的详细过程
  13. 燃烧远征怀旧服务器人数小程序,《魔兽世界怀旧服》燃烧的远征制作人访谈 详细讲解新版本...
  14. python 数字加法运算_Python程序查找两个数字的加法(4种不同方式)
  15. 极光短信在程序中(JAVA)的使用
  16. 微光系列之青春无敌美少女
  17. 抖音爱心c语言程序,抖音上用记事本编写爱心小程序教程
  18. centos 7.6 安装Netbackup 9.1
  19. sqoop 导数据从 mysql 到 hdfs,load 进 hive
  20. 基于低秩张量的高光谱图像重建理论基础-基础知识学习

热门文章

  1. 大力发展先进制造业和装备制造业-高端数控机床(组合机床和立柱移动式三坐标及其基础模块和功能模块规划设计图册技术)
  2. 小米2s的座充,看看这个是什么芯片? - 电池综合DIY(Flashlight Electronics-Batteries Include - 手电大家谈-手电筒爱好者之家...
  3. 2021临湘高考成绩查询,2021湖南地区高考查分时间
  4. ctrl +F5刷新的一个问题
  5. matlab如何打开xlsx表格,matlab 读取word的表格
  6. Python中@符号的用法
  7. 世界末日生存服务器中断,生存新作《最后的绿洲》服务器检修 Steam可全额退款...
  8. windows win10装机软件清单
  9. 【计算机网络】同步和异步
  10. 如何做好APP消息推送