park与unpark

在使用park与unpark的时候就在疑惑为什么先调用unpark时后park就不会阻塞,现在就总结一下原理

@Slf4j
public class ParkAndUnpark {public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {LockSupport.park();log.debug("T1线程");}, "T1");log.debug("Main线程");t1.start();Thread.sleep(2000);LockSupport.unpark(t1);}
}


可以看到这个还是比较符合我们正常情况,因为先执行的是park再执行的是unpark

那么先执行unpark再执行park呢?

@Slf4j
public class ParkAndUnpark {public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {log.debug("start");try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}log.debug("park");LockSupport.park();log.debug("T1线程");}, "T1");log.debug("Main线程");t1.start();Thread.sleep(2000);LockSupport.unpark(t1);log.debug("unpark");}
}


你会发现其实也可以,你也会感到疑惑为什么呢?park加锁后没有unpark为啥还是可以执行?

特点

与 Object 的 wait/notify 相比

wait,notify 和 notifyAll 必须配合 Object Monitor 一起使用,而 park,unpark 不必
park & unpark 是以线程为单位来【阻塞】和【唤醒】线程,而 notify 只能随机唤醒一个等待线程,notifyAll
是唤醒所有等待线程,就不那么【精确】
park & unpark 可以先 unpark,而 wait & notify 不能先 notify

原理

每个线程都有自己的一个 Parker 对象,由三部分组成 _counter_cond_mutex 打个比喻

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

调用 park 就是要看需不需要停下来歇息

  • 如果备用干粮耗尽,那么钻进帐篷歇息
  • 如果备用干粮充足,那么不需停留,继续前进

调用 unpark,就好比令干粮充足

  • 如果这时线程还在帐篷,就唤醒让他继续前进
  • 如果这时线程还在运行,那么下次他调用 park 时,仅是消耗掉备用干粮,不需停留继续前进

因为背包空间有限,多次调用 unpark 仅会补充一份备用干粮

Parker起始状态


其中_counter = 0

调用park方法

  1. 当前线程调用park方法
  2. 检查 _counter ,本情况为 0,这时,获得 _mutex 互斥锁
  3. 线程进入 _cond 条件变量阻塞

调用unpark

  1. 调用 Unsafe.unpark(Thread-0) 方法,设置 _counter 为 1
  2. 唤醒 _cond 条件变量中的 Thread_0
  3. Thread-0 恢复运行
  4. 设置 _counter 为 0

为啥先调用unpark时,第一次park不会阻塞其原因就是调用时候设置了_counter 为 1 所以第一次不会阻塞,但是不管调用多少次unpark只会设置为1

Java中的锁-park/unpark相关推荐

  1. Java中的锁原理、锁优化、CAS、AQS详解

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:景小财 www.jianshu.com/p/e674ee68 ...

  2. 一篇blog带你了解java中的锁

    前言 最近在复习锁这一块,对java中的锁进行整理,本文介绍各种锁,希望给大家带来帮助. Java的锁 乐观锁 乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人 ...

  3. Java中的锁[原理、锁优化、CAS、AQS]

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:用好Java中的枚举,真的没有那么简单!个人原创+1博客:点击前往,查看更多 作者:高广超 链接:https:/ ...

  4. Java中的锁原理、锁优化、CAS、AQS详解!

    阅读本文大概需要 2.8 分钟. 来源:jianshu.com/p/e674ee68fd3f 一.为什么要用锁? 锁-是为了解决并发操作引起的脏读.数据不一致的问题. 二.锁实现的基本原理 2.1.v ...

  5. JAVA 中无锁的线程安全整数 AtomicInteger介绍和使用

    转载自 http://blog.csdn.net/bigtree_3721/article/details/51296064 JAVA 中无锁的线程安全整数 AtomicInteger,一个提供原子操 ...

  6. 面试官让我讲讲Java中的锁,我笑了

    转载自  面试官让我讲讲Java中的锁,我笑了 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容如下: 公平锁/非公平锁 可重入锁 独享锁/共享锁 互斥锁 ...

  7. Java中的锁(转)

    Java中的锁 锁像synchronized同步块一样,是一种线程同步机制,但比Java中的synchronized同步块更复杂.因为锁(以及其它更高级的线程同步机制)是由synchronized同步 ...

  8. 一文足以了解什么是 Java 中的锁

    作者 |  cxuan 责编 | Elle Java 锁分类 Java 中的锁有很多,可以按照不同的功能.种类进行分类,下面是我对 Java 中一些常用锁的分类,包括一些基本的概述 从线程是否需要对资 ...

  9. 关于Java中的锁,看这一篇就够了(总结篇)

    文章目录 锁的概念 锁的分类 一.什么是悲观锁? Java中的悲观锁有哪些 synchronized 基于AQS的实现类 二.什么是乐观锁? Java中的乐观锁有哪些 Valotile Java内存模 ...

最新文章

  1. indows上的android开发环境软件架构5
  2. html表单c 后台如何接受,前台提交整个表单数据,后台实体类接收
  3. UBUNTU安装搜狗
  4. jquery form 序列化
  5. 【原创】字符串工具类--找出单元字符串
  6. etrace 跟踪程序函数动态执行流程
  7. 虚拟机批量安装LINUX,基于vmware workstation的 pxe + kickstart批量安装linux
  8. aix如何安装mysql_AIX下安装Mysql
  9. mysql key_block_size_Mysql入门mysql Key_buffer_size参数的优化设置
  10. python函数编程训练题_Python文件与函数练习题
  11. python3示例_Python3 实例(七)
  12. oracle 10g 企业管理器无法打开解决方法
  13. lamba List 转 Map
  14. android 9格式吗,Android Studio中关于9-patch格式图片的编译错误
  15. 数据结构练习题之树和图(附答案与解析)
  16. 6000万条GitHub帖子告诉你:工作状态与表情符号强相关
  17. 【转】MEF程序设计指南四:使用MEF声明导出(Exports)与导入(Imports)
  18. jieba库初识与运用
  19. matlab中标准化降水指数程序,标准化降水指数(SPI)计算程序
  20. html 简繁转换 批量,繁简文件批量互转程序

热门文章

  1. Vue【vue-seamless-scroll】滚动组件及注意事项
  2. rabbitmq添加插件和配置文件的添加
  3. 大尺寸卫星图像目标检测:yoloT
  4. Verilog训练笔记(2)——数据降速增宽
  5. 51单片机入门——STC89C52RC控制步进电机进行转动、调速
  6. PS A11选区和选框工具
  7. flutter友盟分享_Flutter中使用友盟统计
  8. 小白学习HCIA2022
  9. mount 挂载 img
  10. 形容linux技术视野的词,火焰图:全局视野的Linux性能剖析