长久以来对线程阻塞与唤醒经常我们会使用object的wait和notify,除了这种方式,java并发包还提供了另外一种方式对线程进行挂起和恢复,它就是并发包子包locks提供的LockSupport。

LockSupport提供了park和unpark进行线程的挂起和恢复操作,来看一个简单挂起和恢复的简单例子:

由于编辑格式限制,直接贴代码有人反映会显得很杂乱,之后有关代码将直接放图片,上例子中描述了一个场景,周末了某男兴奋的去打游戏了,于是被游戏阻塞了(park),其他的都不干了,这个时候女朋友打来电话,别打游戏了,陪她逛街,把男朋友从游戏中唤醒(unpark)。LockSupport使用方式和wait/notify很类似,LockSupport使用更加灵活,unpark可以先于park进行调用,因为这个特点,我们可以不用担心挂起和恢复时序问题,就如流打开了必须关闭这中类似问题,给我们带来很多编程麻烦。

LockSupport底层是有Unsafe提供的两个基本同步语句,这个在关于Unsafe介绍中已经做了分析,LockSupport是对这两个函数的进一步封装,除了例子中方法,它还提供了其他几个功能。

以上为LockSupport属性,Unsafe这个很好理解,整个LockSupport的实现都是基于Unsafe的两个方法,SEED、PROBE、SECONDARY都是Thread类中为了对象上图中三个字段的相对地址偏移量,功能主要用于ThreadLocalRandom类进行随机数生成,它比Random性能要高的多,可阅读该篇文章了解详细(https://my.oschina.net/adan1/blog/159371),虽然LockSupport定义这三个字段但是基本没有使用,可能之后JDK会有所变化吧。这里parkBlockerOffset字段,解释起来就是挂起线程对象的偏移地址,对应的是Thread类的parkBlocker。

这个字段可以理解为专门为LockSupport而设计的,它被用来记录线程是被谁堵塞的,当程序出现问题时候,通过线程监控分析工具可以找出问题所在。注释说该对象被LockSupport的getBlocker和setBlocker来获取和设置,且都是通过地址偏移量方式获取和修改的。由于这个变量LockSupport提供了park(Object parkblocker)方法。

代码很好理解获取当前线程,通过偏移量的方式设置parkBlocker的值,将调取unsafe.park把线程挂起,线程被恢复后,修改blocker为null。

那我们可以把文章开篇例子修改的更加应景一些,如下:

定义一个blocker者名字叫“游戏”,某男被游戏堵塞park(a),我们通过jstack pid获取当前线程相关信息(jstack用于打印出给定的Java进程ID或core file或远程调试服务的Java堆栈信息):

可以看到当前线程状态是WAITING,确实通过unsafe.park挂起的,blocker为一个字符串类型的id为0x…的。通过mat工具可以知道这个id对应得对象即为变量名为game的string对象。若不设置blocker,则是空的,如下:

只是将线程进行了挂起,无blocker。

那么LockSupport的park/unpark与wait/notify有啥区别呢?首先wait/notify对线程所起的作用和park/unpark是一样的,如下为使用wait阻塞线程的线程状态:

也是waiting,只是方式是调取Object.wait。说明产生的效果是一样,那来继续分析一下两者实现机制。

它俩面向操作的对象不同,通过上述分析,我们知道LockSupport阻塞和唤醒线程直接操作的就是线程,所以从语义上讲,它更符合常理,或者叫更符合语义。而Object的wait/notify它并不是直接对线程操作,它是被动的方法,它需要一个object来进行线程的挂起或唤醒。

park/unpark使用起来会更加的灵活、方便。在调用对象的wait之前当前线程必须先获得该对象的监视器(synchronized),被唤醒之后需要重新获取到监视器才能继续执行。而LockSupport则不会,如例子中所示,它可以随意进行park或者unpark。

两则虽然都能更改线程状态为WAITING,但由于实现的机制不同,所以不会产生交集,就是park挂起线程,notify/notifyall是无法进行唤醒的。我们来看个例子。就好比你在打游戏,一个陌生大妈让你逛街去,你应该不会去吧(特殊需求的除外)。如下例子(代码这样写也是绝了,仅仅举例子):

使用notify还有一个问题就是,有时候为了保险起见大多数都用notifyall,notify只能唤醒一个线程,假如有两个被阻塞的话,另外一个就悲剧了。

除此之外,park也可以响应中断异常,关于中断异常详讲也需要一大篇文章,这里不做详细分析,来看一下park响应中断过程。

对开篇代码改造一下,还是某男打游戏,且深深陷入其中(park),突然屎意甚浓,于是被其中断(interrupt),然后某男去拉屎去了。最终线程退出了运行,在这里你会发现,park并不会抛出InterruptedException异常。那问题来,不抛出异常,那和正常的unpark有何区别?不能拉屎中断和女朋友召唤效果一样吧。这里就要依赖线程的interruptedstatus,如果线程被中断而退出阻塞该状态会被修改为true。如下可获取到当前interrupted status。

总结起来LockSupport有以下不同和特点:

  1. 其实现机制和wait/notify有所不同,面向的是线程。

  2. 不需要依赖监视器

  3. 与wait/notify没有交集

  4. 使用起来更加灵活方便

java并发包系列---LockSupport相关推荐

  1. Java并发包源码学习系列:同步组件CountDownLatch源码解析

    文章目录 CountDownLatch概述 使用案例与基本思路 类图与基本结构 void await() boolean await(long timeout, TimeUnit unit) void ...

  2. Java并发包源码学习之AQS框架(三)LockSupport和interrupt

    接着上一篇文章今天我们来介绍下LockSupport和Java中线程的中断(interrupt). 其实除了LockSupport,Java之初就有Object对象的wait和notify方法可以实现 ...

  3. 并发编程笔记——第六章 Java并发包中锁原理剖析

    一.LockSupport工具类 JDK中的rt.jar包里的LockSupport是个工具类,它的主要作用是挂起和唤醒线程,该工具类是创建锁和其他同步类的基础.LockSupport类与每个使用它的 ...

  4. 高并发基础之Java并发包

    转自:https://my.oschina.net/hosee/blog/607677 其他资料: https://my.oschina.net/zhupanxin/blog/269037 摘要: 本 ...

  5. 腾讯面试题Java 并发包之线程池综述

    Java 并发包之线程池综述 ■ 线程池的创建 在Java中,您可以通过调整-Xss参数来调节每个线程栈的大小(64bit系统默认1024KB),当减小该值时意味着可以创建更多的线程数,但问题是JVM ...

  6. 死磕java并发cas_死磕 java并发包之AtomicInteger源码分析

    问题 (1)什么是原子操作? (2)原子操作和数据库的ACID有啥关系? (3)AtomicInteger是怎么实现原子操作的? (4)AtomicInteger是有什么缺点? 简介 AtomicIn ...

  7. 深入java并发包源码(三)AQS独占方法源码分析

    深入java并发包源码(一)简介 深入java并发包源码(二)AQS的介绍与使用 深入java并发包源码(三)AQS独占方法源码分析 AQS 的实现原理 学完用 AQS 自定义一个锁以后,我们可以来看 ...

  8. 详解Java多线程编程中LockSupport类的线程阻塞用法

    转载自  详解Java多线程编程中LockSupport类的线程阻塞用法 LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了基本的线程同步原语.LockSupport实际 ...

  9. Java并发包基石-AQS详解

    目录 1 基本实现原理 1.1 如何使用 1.2 设计思想 2 自定义同步器 2.1 同步器代码实现 2.2 同步器代码测试 3 源码分析 3.1 Node结点 3.2 独占式 3.3 共享式 4 总 ...

最新文章

  1. [转] asp.net core Introducing View Components
  2. 五大存储模型关系模型、键值存储、文档存储、列式存储、图形数据
  3. 安全是一个系统问题包括服务器安全,信息安全技术题库:信息泄露对于Web服务器的危害在于( )。...
  4. (原)产品化:架构、过程管理
  5. 小程序开发实战学习笔记
  6. Jenkins 中以构建 Tag 来实现版本管理
  7. C#中的两把双刃剑:抽象类和接口
  8. dev shm php,/dev/shm 介绍 --转载
  9. 浅谈音视频网络通信中的延时优化
  10. 分蛋糕问题 —— 9 个烧饼分给 10 个人
  11. 学习c语言的小程序,C语言小程序学习
  12. 人脸识别考勤机软件驱动安装和设置
  13. android 图片浏览 app 排行版,安卓图片浏览软件哪个好_安卓图片浏览app推荐_图片浏览app软件排行...
  14. 下行期的资本,正在追逐「猫品牌」
  15. 多行文本溢出隐藏省略号
  16. 2021最新微信域名链接检测工具 微信域名拦截检测接口
  17. 【C语言】求一个数有多少位
  18. ulpfec,flexFec,Pro-MPEG cop3协议对比
  19. 非易失性存储器Flash和EEPROM之间的差异与优缺点
  20. ANSYS渡槽槽身动水压力的施加(2)——U型渡槽

热门文章

  1. c语言程序设计编程解读,C语言程序设计第三次实验报告解读
  2. Tomcat中session的管理机制
  3. linux sh脚本 递增,Linux shell 脚本实现进度框
  4. 如何查询spark版本_掌握Spark SQL中的查询执行
  5. java中开根号求三角形_Java编程 如何计算三角形的内切圆半径?
  6. java委托机制教程_通过反射实现Java下的委托机制代码详解
  7. ip 地址 192.168.1.255 代表( )。_判定IP地址合法性的三种方法
  8. 计算机仿真实训系统的企业排名,闵行区虚拟仿真实训平台企业-哪家不错
  9. mac mysql mysqldump_Mac下Mysql导出sql语句的方法及可能遇到的mysqldump: command not found...
  10. (一) shario教程资料