JUC 高并发编程(13):LockSupport 概述, wait 与 sleep与park的区别
LockSupport
LockSupport 是一个线程阻塞工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞,阻塞之后也有对应的唤醒方法。归根结底,LockSupport调用的Unsafe中的native代码
- 通过park()和unpark(thread)方法来实现阻塞和唤醒线程的操作
- LockSupport类使用了一种名为
Permit(许可)
的概念来做到阻塞和唤醒线程的功能,每个线程都有一个许可(permit),permit只有两个值 1和零,默认是零
注意上面的123方法,都有一个blocker,这个blocker是用来记录线程被阻塞时被谁阻塞的。用于线程监控和分析工具来定位原因的。
① 阻塞方法
permit默认是0,所以一开始调用park()方法,当前线程就会阻塞,直到别的线程将当前线程的permit设置为1时, park方法会被唤醒,然后会将permit再次设置为0并返回permit 表示当前线程是否处于运行状态
- static void park( ):底层是unsafe类native方法
- static void park(Object blocker)
- blocker是用来记录线程被阻塞时被谁阻塞的。用于线程监控和分析工具来定位原因的。
setBlocker(t, blocker)
方法的作用是记录t线程是被broker阻塞的。
② 唤醒方法(注意这个permit最多只能为1)
调用 unpark(thread)
方法后,就会将 thread 线程的许可 permit设置成1
(注意多次调用unpark方法,不会累加,permit值还是1)会自动唤醒thread线程,即之前阻塞中的 LockSupport.park()方法会立即返回。
park, wait, sleep, interrupt, yeild 对比
JVM线程状态: NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED
- BLOCKED:是等待获得对象锁
- WAITING是调用了:wait, sleep, park
1. 线程让步: yield()
yield() 的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;
- 但是,并不能保证在当前线程调用
yield()
之后,其它具有相同优先级的线程就一定能获得执行权; - 也有可能是当前线程又进入到“运行状态”继续运行!
- 在操作系统层面让线程从running变成ready状态,等待继续被调度。在jvm的线程状态还是RUNNABLE
2、阻塞线程,并且释放锁: Object中的wait()和notify()
- 进入 TIMED_WAITING 状态,让出锁,并进入对象的等待
- 因为wait需释放锁,所以必须在synchronized中使用(没有锁时使用会抛出IllegalMonitorStateException)
- notify也要在synchronized使用,并且应该指定对象
- synchronized(),wait(),notify() 对象必须一致,一个synchronized()代码块中只能有1个线程wait()或notify()
3、线程休眠:sleep()
- sleep() 定义在Thread.java中。
- sleep() 的作用是让当前线程休眠,即当前线程会从“运行状态”进入到“休眠(阻塞)状态”。
- sleep()会指定休眠时间,线程休眠的时间会大于/等于该休眠时间;在线程重新被唤醒时,它会由“阻塞状态”变成“就绪状态”,从而等待cpu的调度执行
- 进入TIMED_WAITING状态,不出让锁
4、LockSupport中的park() 和 unpark()
总结一下,LockSupport比Object的wait/notify有两大优势:
- LockSupport不需要在同步代码块里 。所以线程间也不需要维护一个共享的同步对象了,实现了线程间的解耦。说明:park和wait的区别。wait让线程阻塞前,必须通过synchronized获取同步锁。
- unpark函数可以先于park调用,所以不需要担心线程间的执行的先后顺序。
- park, 进入WAITING状态,对比wait不需要获得锁就可以让线程WAITING,通过unpark唤醒
5. join
等待该线程终止。
- 等待调用join方法的线程结束,再继续执行。
- 如:t.join();//主要用于等待t线程运行结束,若无此句,main则会执行完毕,导致结果不可预测。
yield() 与 wait()的比较
我们知道 ,wait() 的作用是让当前线程由“运行状态”进入“等待(阻塞)状态”的同时,也会释放同步锁 。而yield()的作用是让步,它也会让当前线程离开“运行状态”。它们的区别是:
- (1) wait() 是让线程由“运行状态”进入到“等待(阻塞)状态”,而不yield()是让线程由“运行状态”进入到“就绪状态”。.
- (2) wait()是会线程释放它所持有对象的同步锁,而yield()方法不会释放锁。
sleep() 与 wait()的比较:
- 我们知道,wait()的作用是让当前线程由“运行状态”进入“等待(阻塞)状态”的同时,也会释放同步锁。而sleep()的作用是也是让当前线程由“运行状态”进入到“休眠(阻塞)状态”。
- 但是,wait()会释放对象的同步锁,而sleep()则不会释放锁。(sleep 不释放锁的原因,是因为 sleep 中可以传入睡眠时间,时间一到就将该线程加入到就绪队列中,因此不能释放锁,释放锁后重新获得锁的时间不可控)
sleep()与yield()的比较:
sleep和yield的区别在于, sleep可以使优先级低的线程得到执行的机会, 而yield只能使同优先级的线程有执行的机会.
JUC 高并发编程(13):LockSupport 概述, wait 与 sleep与park的区别相关推荐
- Java JUC高并发编程(三)-CallableJUC辅助类
目录 一.Callable接口 二.JUC辅助类 1.减少计数CountDownLatch 2.循环栅栏CyclicBarrier 3.信号灯Semaphore 一.Callable接口 Callab ...
- Java JUC高并发编程(一)
目录 一.概述 二.Lock接口 三.线程间的通信 解决虚假唤醒问题 Lock通信示例: 四.线程间定制化通信 一.概述 JUC就是java.util.concurrent工具包的简称,这是一个处理线 ...
- 【JUC高并发编程】—— 初见JUC
一.JUC 概述 什么是JUC JUC 是 Java并发编程的缩写,指的是 Java.util.concurrent 即Java工具集下的并发编程库 [说白了就是处理线程的工具包] JUC提供了一套并 ...
- 详解JUC高并发编程
JUC并发编程 并发编程的本质:充分利用CPU的资源 问题:JAVA可以开启线程吗? 不能:最底层是本地方法,底层是C++,Java无法直接操作硬件 1.线程里有几个状态 NEW, 新生 RUNN ...
- 【JUC高并发编程】—— 再见JUC
一.读写锁 读写锁概述 1️⃣ 什么是读写锁? 读写锁是一种多线程同步机制,用于在多线程环境中保护共享资源的访问 与互斥锁不同的是,读写锁允许多个线程同时读取共享资源,但在有线程请求写操作时,必须将其 ...
- JUC高并发编程从入门到精通(全)
目录 前言 1. Lock接口 1.1 复习synchronized 1.2 Lock接口 1.3 Lock方法 1.4 两者差异 2. 线程间通信 2.1 synchronized案例 2.2 Lo ...
- 高级技术之 JUC 高并发编程
1,什么是 JUC 1.1 JUC简介 JUC 就是java.util.concurrent 工具包的简称,这一个专门用来处理线程的工具包,JDK1.5开始出现 1.2 进程与线程 **进程(Proc ...
- 《尚硅谷高级技术之JUC高并发编程》学习笔记11—— Fork / Join 框架
文章目录 Fork / Join 框架简介 fork() 方法 join() 方法 Fork / Join 框架的异常处理 入门案例 总结 Fork / Join 框架简介 Fork / Join 它 ...
- java线程高并发编程
java线程详解及高并发编程庖丁解牛 线程概述: 祖宗: 说起java高并发编程,就不得不提起一位老先生Doug Lea,这位老先生可不得了,看看百度百科对他的评价,一点也不为过: 如果IT的历史,是 ...
最新文章
- LabVIEW读写各类格式图像的方法(基础篇—1)
- Atitit.java c#这类编程语言的设计失败点attilax总结
- linux 账号和密码文件 /etc/passwd和/etc/shadow 简介
- Visual C# 2010 实现资源管理器
- pyecharts运行了但是没有图_新版pyecharts,Python可视化so easy and powerful !
- mysql 5.7.13 安装配置方法图文教程(linux)
- 信息学奥赛一本通 1043:整数大小比较 | OpenJudge NOI 1.4 05
- 用python计算绩点的代码_【Python】计算GPA
- [水力建模]EPANET代码解读1
- 一图抵千言:带你快速学会 GoogLeNet 神经网络 | CSDN 博文精选
- 全网最详细的hive-site.xml配置文件里如何添加达到Hive与HBase的集成,即Hive通过这些参数去连接HBase(图文详解)...
- 服务器位置设置,服务器部署位置
- 如何利用JClassLib修改.class文件
- python实现抠图_python和opencv实现抠图
- wince 德赛西威2413_德赛西威NAV230凯立德2016春季专版C2134-C7M07-3921J0S
- 冀教版小学三年级上册计算机教案,冀教版小学三年级上册信息技术教案三篇
- Visual Studio2022编译报错解决方法
- 用Bittorrent和PHP搭建BT Tracker服务器和发布页
- 全球知名的人工智能研究院(实验室)
- css布局——GFC
热门文章
- 微信小程序层叠轮播图、3D轮播图
- 我的世界手机有PHP的开服器下载,《我的世界手机版》怎么用电脑开服,pocketminePC版使用教程...
- 【git】Git删除本地分支和删除远程分支
- 产品设计在生活中——设计与生产的关系(3)
- 远程桌面连接:出现身份验证错误,要求的函数不受支持报错,解决方法
- 函数计算乘积python multi_两个函数的乘积
- 阿里无线11.11 | 手机淘宝移动端接入网关基础架构演进之路
- 全球与中国厨房除油剂市场现状及未来发展趋势
- 最新iApp影视解析源码+实测可用
- IDEA中使用git提交代码