并发编程学习(六):park、unpark

news2024/11/19 3:18:24

1、 park、unpark介绍

parkunpark它们是LockSupport类中的方法,内部调用的是Unsafe类中的native方法。

 // 暂停当前线程,暂停后,线程状态变为 WAITING

LockSupport.park();

// 恢复某个线程的运行,恢复后线程状态变为RUNNING

LockSupport.unpark(要恢复的线程对象);

        先park再unpark的方式是容易理解的。但还有一个场景,先unpark后再次执行park方法,也不会阻塞调用了park方法的线程。理解为park方法就是校验获取一个通行令牌,而unpark方法是获取到一个通行令牌的过程。先执行unpark方法,代表先获得了通行令牌。在另一个线程调用park方法时,校验到这个令牌存在,消耗掉这个令牌然后就可以继续往下走。

代码示例: 

    public static void main(String[] args) {

        Thread t1 = new Thread(() -> {
            log.debug("start...");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.debug("park...");
            LockSupport.park();
            log.debug("resume...");
        },"t1");

        t1.start();

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.debug("unpark...");
        LockSupport.unpark(t1);

    }
}

输出结果:

15:45:21.606 [t1] DEBUG com.example.common.thread.TestLockSupport - start...
15:45:22.617 [t1] DEBUG com.example.common.thread.TestLockSupport - park...
15:45:56.229 [main] DEBUG com.example.common.thread.TestLockSupport - unpark...
15:49:31.797 [t1] DEBUG com.example.common.thread.TestLockSupport - resume...

2、wait/notify与park/unpark区别 

  1. wait、notify 、notifyAll必须配合Object Monitor (即对象锁)一起使用,而park、unpark不必。
  2. park、unpark是以线程为单位来【阻塞】和【唤醒】线程; 而notify只能随机唤醒一个等待线程,notifyAll是唤醒所有等待线程,就不那么【精确】。
  3. park、unpark可以先unpark;而wait、notify不能先notify。

3、 park、unpark原理

每个线程都有自己的一个Parker对象(该Parker对象是底层的c代码实现的),由三部分组成:

_counter(代表了一个标志位)、_cond(表了内部的一个阻塞队列) 和 _mutex 。

比如:

        线程就像一个旅人,Parker就像他随身携带的背包,条件变量就好比背包中的帐篷。_counter就好比背包中的干粮(0为耗尽,1为充足)。

        调用park就是要看需不需要停下来歇息。如果备用干粮耗尽,那么钻进帐篷休息;如果备用干粮充足,那么不需要停留,继续前进。

        调用unpark就好比令干粮充足。如果这时线程还在帐篷,就唤醒,让他继续前进;如果这时线程还在运行,那么下次他调用park时,仅是消耗备用干粮,需不要停留继续前进,因为背包空间有限,多次调用unpark仅会补充一份备用干粮。

1、当线程调用Unsafe.park()方法。

2、检查_counter ,本情况为0,这时获得_mutex互斥锁。

3、线程进入_cond条件变量阻塞。

4、设置_counter=0

1、调用Unsafe.unpark(Thread_0)方法,设置_counter为1 。

2、唤醒_cond条件变量中的Thread_0。

3、Thread_0恢复运行。

4、设置_counter为0.

1、 调用Unsafe.unpark(Thread_0)方法,设置_counter为1 。

2、当前线程调用Unsafe.park()方法。

3、检查_counter,本情况为1,这时线程无需阻塞,继续运行。

4、设置_counter为0。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/110951.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

炸弹(二分图最大匹配 = 二分图最小顶点覆盖)

D-炸弹_2022图论班第一章图匹配例题与习题 (nowcoder.com) 看题解前先理解二分图最小点集覆盖 最大匹配 一、什么是最小点覆盖 点覆盖的概念定义: 对于图G(V,E)中的一个点覆盖是一个集合S⊆V使得每一条边至少有一个端点在S中。 最小点覆盖:点个数最少的…

《编译原理》实验一:熟悉实验环境VSCode并完成正则表达式转换为NFA

目录 实验一 熟悉实验环境VSCode并完成正则表达式转换为NFA 一、实验目的 二、预备知识 三、实验内容 VSCode的基本使用方法 安装和启动VSCode VSCode的窗口布局 使用VSCode将项目克隆到本地磁盘 使用VSCode登录平台 查看项目中的文件 实验源代码 演示程序的执行过程 四、实验过…

LeetCode Hot 100~Day2

目录 三数之和 电话号码的字母组合 括号生成 合并k个升序链表 下一个排列 搜索旋转排序数组 在排序数组中查找元素的第一个和最后一个位置 组合总数 全排列 旋转图像 三数之和 题目链接:15.三数之和 示例 输入:nums [-1,0,1,2,-1,-4] 输…

金山云将于12月30日在港交所上市:不发行新股,王育林已辞职

12月23日,金山云(NASDAQ:KC,HK:03896)发布公告称,拟通过介绍方式在港交所主板上市,代码为“03896”。按照计划,金山云将于2022年12月30日正式登陆港交所,不发行新股融资。 据贝多财…

我写这10+个JavaScript单行代码,被组长夸代码写得优雅!

大厂面试题分享 面试题库 前端面试题库 (面试必备) 推荐:★★★★★ 地址:前端面试题库 JavaScript 非常大的特点容易上手且非常灵活,代码实现方式五花八门;有时候能一行代码解决,就尽量不用…

MES系统与WMS系统的区别在哪里?

从字面上理解 MES是一套面向制造企业车间执行层的生产信息化管理系统。 WMS是仓储管理系统(WarehouseManagentsystem)的缩写,是通过入库、出库、调拨、管理等功能,实现一体化批量管理。 从用法上理解 WMS仓库管理系统主要采用条码技术,可及…

认识 微内核架构

微内核架构 1 说明背景 关于宏内核、微内核、混合内核,都是相对而言的概念。 宏内核: 通用的操作系统,将操作系统内核的所有模块放置在内核态运行,具备直接操作硬件的能力。例如 UNIX/Linux, FreeBSD 等微内核: 简单的操作系统,…

深度学习训练营之海贼王人物识别

深度学习训练营之海贼王人物识别原文链接环境介绍前置工作设置GPU导入数据数据查看数据预处理加载数据可视化数据检查数据配置数据集prefetch()功能详细介绍:归一化查看归一化后的数据构建VGG-16网络网络结构编译模型训练结果可视化原文链接 🍨 本文为&a…

ELK集群部署---ElasticSearch集群的部署

1. 环境规划: 主机名IP地址角色node1192.168.56.111 ElasticSearch(master) Zookeeper Kafka node2192.168.56.112 ElasticSearch(slave) Kibana Zookeeper Kafka node3192.168.56.113 ElasticSearch(slave) Zookeeper Kafka node4192.168.56.114 Logstash Filebe…

4. Json数据传递与接收

由于Json数据传递与接收在以后的开发中是主流&#xff0c;所以把它拿出来独立记一篇笔记&#xff0c;其他的笔记太庞杂了。 1. json数据参数传递实现步骤 1.1 添加json数据转换相关坐标 <dependency><groupId>com.fasterxml.jackson.core</groupId><ar…

HBCPC2022-河北省大学生程序设计竞赛

部分题解7-4 键盘故障7-6 筷子7-8 方7-9 优美的字符串7-4 键盘故障 签到题&#xff0c;直接遍历字符串&#xff0c;相同则跳过&#xff0c;不相同则输出 题目链接&#xff1a;https://pintia.cn/problem-sets/1584003400735793152/exam/problems/1584003481883000835 AC代码&a…

业聚医疗在港交所上市:市值约76亿港元,钱永勋、刘桂祯夫妇控股

12月23日&#xff0c;业聚医疗集团控股有限公司&#xff08;下称“业聚医疗”&#xff0c;HK:06929&#xff09;在港交所上市。本次上市&#xff0c;业聚医疗的发行价为8.80港元/股&#xff0c;全球发行发售5463.30万股&#xff0c;募集资金总额约为4.81亿港元&#xff0c;募资…

java基于ssm,jsp鞋城源码卖鞋服装男鞋商城女鞋商城项目源码

ssm开发的网上鞋城系统&#xff0c;主要有商品分类&#xff0c;列表&#xff0c;详情&#xff0c;加入购物车&#xff0c;订单&#xff0c;收货地址等功能&#xff0c;单商家登录后台可以发布商品&#xff0c;上下架商品&#xff0c;发货退款等管理订单。 演示视频&#xff1a;…

【开源项目】历史数据迁移

历史数据迁移 项目地址&#xff1a;https://gitee.com/xl-echo/dataMigration 历史迁移解决方案。微服务的架构为基础&#xff0c;使用多种设计模式&#xff0c;如&#xff1a;单利、桥接、工厂、模板、策略等。其中涉及的核心技术有&#xff0c;多线程、过滤器等。致力于解决…

django 中间件基础介绍

1、简单的理解&#xff0c;1个中间件就是1个类&#xff0c;中间件一般可以用来检查用户是否登录。 2、用户通过浏览器访问视图函数的内容需要先通过中间件&#xff0c;通过中间件后再到视图函数&#xff0c;返回结果也需要通过中间件&#xff0c;如下草图 3、自定义一个中间件…

一文读懂Linux内核处理器架构中的栈

栈是什么&#xff1f;栈有什么作用&#xff1f; 首先&#xff0c;栈 (stack) 是一种串列形式的 数据结构。这种数据结构的特点是 后入先出 (LIFO, Last In First Out)&#xff0c;数据只能在串列的一端 (称为&#xff1a;栈顶 top) 进行 推入 (push) 和 弹出 (pop) 操作。根据…

基于CNN卷积神经网络 猫狗图像识别

目录 一&#xff1a;数据集准备 二&#xff1a;读取自己的数据集 三&#xff1a;搭建网络 训练模型 四&#xff1a;猫狗图像识别 一&#xff1a;数据集准备 从官网下载比较麻烦&#xff0c;可根据以下链接&#xff0c;从百度网盘获取数据集 https://pan.baidu.com/s/13hw4L…

【Docker系列】容器环境配置

个人名片&#xff1a; 对人间的热爱与歌颂&#xff0c;可抵岁月冗长&#x1f31e; Github&#x1f468;&#x1f3fb;‍&#x1f4bb;&#xff1a;念舒_C.ying CSDN主页✏️&#xff1a;念舒_C.ying 个人博客&#x1f30f; &#xff1a;念舒_C.ying Docker可以让开发者打包他们…

55.函数的参数传递

55.函数的参数传递 文章目录55.函数的参数传递1.函数的参数2.参数的传递方法3.使用位置参数传递参数4.使用关键字传递参数1.函数的参数 自定义函数有2种参数&#xff1a;形式参数和实际参数。 def语句中的参数不是实际参数&#xff0c;我们称之为形式参数&#xff0c;简称形参…

C51——添加震动开盖功能,使用外部中断优化

void main() {double dis;Timer1Init();Time0Init();SG90_Init();while(1){dis get_dis();if(dis<10 || SW1 0||Vibrate 0){OpenTheLed5();opengaizi(); // }else{CloseTheLed5();closegaizi();}} }像这样只是简单的通过震动模块传给单片机一个让舵机转动&#xff0c;出来…