写点什么

【Java 深入学习】Park&Unpark 的深入学习讲解

作者:Geek_65222d
  • 2022 年 10 月 11 日
    河南
  • 本文字数:1415 字

    阅读完需:约 5 分钟

基本使用

// 暂停当前线程 LockSupport.park(); // 恢复某个线程的运行 LockSupport.unpark(暂停线程对象)
复制代码


当在某线程使用 LockSupport.park();后此线程变为 WATING 状态

代码示例

@Slf4j(topic = "c.TestParkUnpark")public class TestParkUnpark {    public static void main(String[] args) {        Thread t1 = new Thread(() -> {            log.debug("start...");            sleep(1);            log.debug("park...");            LockSupport.park();            log.debug("resume...");        }, "t1");        t1.start();
sleep(2); log.debug("unpark..."); LockSupport.unpark(t1); }}
复制代码


结果:


  • 17:22:16.403 c.TestParkUnpark [t1] - start…

  • 17:22:17.412 c.TestParkUnpark [t1] - park…

  • 17:22:18.402 c.TestParkUnpark [main] - unpark…

  • 17:22:18.402 c.TestParkUnpark [t1] - resume…解释:


可以看出我们在 1s 时 LockSupport.park();暂停了线程 t1 在 2s 时 LockSupport.unpark(t1);把 t1 线程恢复


注意:


如果我们此时在 1s 时恢复 t1 线程,2s 时再暂停 t1 线程会怎么样?


@Slf4j(topic = "c.TestParkUnpark")public class TestParkUnpark {    public static void main(String[] args) {        Thread t1 = new Thread(() -> {            log.debug("start...");            sleep(2);            log.debug("park...");            LockSupport.park();            log.debug("resume...");        }, "t1");        t1.start();
sleep(1); log.debug("unpark..."); LockSupport.unpark(t1); }}
复制代码


结果:


  • 17:27:11.949 c.TestParkUnpark [t1] - start…

  • 17:27:12.959 c.TestParkUnpark [main] - unpark…

  • 17:27:13.958 c.TestParkUnpark [t1] - park…

  • 17:27:13.958 c.TestParkUnpark [t1] - resume…


解释:


可以看出我们先 unpark 再 park,t1 线程还是正常运行,和我们对 wait/notify 的理解不一样

特点

LockSupport 的 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 和_mtuex,打个比喻线程就像一个旅行的人,Parker 是它随身携带背包,条件变量就好比背包中的帐篷,_ counter 就好比背包中的备用干粮(0 为耗尽,1 为充足)调用 park 就是要看需不需要停下来休息如果备用干粮耗尽,则去帐篷中休息如果备用干粮充足,那么不需要停留 继续前进调用 unpark,就好比令干粮充足如果此时线程还在帐篷 那么久唤醒他 继续前行如果此时线程还在运行 那么下次他调用 park 时 仅是消耗备用干粮 不需停留继续前进因为背包空间有限 多次调用 unpark 仅会补充一份备用干粮


前提:还没有 park,探究 park 过程的变化


1.当前线程调用 park 方法


2.检查_counter 本情况为 0 此时 获得_mutex 互斥锁


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


4.设置_counter=0


前提:探究先 unpark 后 park 的情况

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

2.当前线程调用 park 方法

3.检查_counter 本情况为 1 此时线程无需阻塞 继续运行

4.设置_counter 为 0

发布于: 刚刚阅读数: 5
用户头像

Geek_65222d

关注

还未添加个人签名 2022.09.09 加入

还未添加个人简介

评论

发布
暂无评论
【Java深入学习】Park&Unpark的深入学习讲解_十月月更_Geek_65222d_InfoQ写作社区