[JUC] LockSupport浅析

LockSupport从入门到深入理解 LockSupport Condition ,wait,notify 阅读详情


LockSupport是Java6引入的一个工具类,它简单灵活,应用广泛。在没有LockSupport之前,线程的挂起和唤醒咱们都是通过Object的wait和notify/notifyAll方法实现。

我们以例子来说明两者之间的区别

wait/notify

线程t执行一段业务逻辑后调用wait阻塞住自己。主线程调用notify方法唤醒线程A,线程A然后打印自己执行的结果:

public class WaitTest {
    public static void main(String[] args) throws Exception {
        final Object obj = new Object();
        Thread t = new Thread(() -> {
            int sum = IntStream.range(0, 11).sum();
            try {
                obj.wait();
            }catch (Exception e){
                e.printStackTrace();
            }
            System.out.println(sum);
        });
        t.start();
        //睡眠一秒钟,保证线程t已经计算完成,阻塞在wait方法
        Thread.sleep(1000);
        obj.notify();
    }
}

执行这段代码,不难发现这个错误:

java.lang.IllegalMonitorStateException
	at java.base/java.lang.Object.wait(Native Method)
	at java.base/java.lang.Object.wait(Object.java:328)
	at com.ctrip.flight.test.concurrent.WaitTest.lambda$main$0(WaitTest.java:16)
	at java.base/java.lang.Thread.run(Thread.java:834)
55
Exception in thread "main" java.lang.IllegalMonitorStateException
	at java.base/java.lang.Object.notify(Native Method)
	at com.ctrip.flight.test.concurrent.WaitTest.main(WaitTest.java:25)

原因很简单,wait和notify/notifyAll方法只能在同步代码块里用。所以将代码修改为如下就可正常运行了:

public class WaitTest {
    public static void main(String[] args) throws Exception {
        final Object obj = new Object();
        Thread t = new Thread(() -> {
            int sum = IntStream.range(0, 11).sum();
            try {
                synchronized (obj) {
                    obj.wait();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
            System.out.println(sum);
        });
        t.start();
        //睡眠一秒钟,保证线程A已经计算完成,阻塞在wait方法
        Thread.sleep(1000);
        synchronized (obj) {
            obj.notify();
        }
    }
}

上述示例中我们在main线程sleep了1秒钟等待t线程执行到wait操作为止,试想如果main线程不sleep,并且先于t线程执行notify方法会发生出什么情况:

public class WaitTest {
    public static void main(String[] args) throws Exception {
        final Object obj = new Object();
        Thread t = new Thread(() -> {
            int sum = IntStream.range(0, 11).sum();
            try {
                synchronized (obj) {
                    obj.wait();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
            System.out.println(sum);
        });
        t.start();
        // 睡眠一秒钟,保证线程t已经计算完成,阻塞在wait方法
        // Thread.sleep(1000); 不等待t线程执行到wait方法
        synchronized (obj) {
            obj.notify();
        }
    }
}

多执行几次会发现JVM进程无法退出,是因为mian线程在执行完notify后退出了,而此时t线程可能刚好执行到wait,再也没有接收到notify了,t线程就一直处于等待状态,因为t不是daemon线程,JVM进程不会退出(只有当当前运行的所有线程都是deamon线程时JVM才会退出)。t线程要先使用synchronized获取obj对象的锁,使得main线程无法执行notify,阻塞在synchronized (obj)操作,接着t线程执行wait操作释放obj的锁,并将自身阻塞起来,main线程重新获得obj的锁,执行notify方法,退出synchronized代码块释放obj锁后t线程在obj.wait()处重新获取锁,继续往下执行。

LockSupport

下面使用LockSupport实现同样的功能:

public class LockSupportTest {
    public static void main(String[] args) throws Exception {
        Thread t = new Thread(() -> {
            int sum = IntStream.range(0, 11).sum();
            LockSupport.park();
            System.out.println(sum);
        });
        t.start();
        LockSupport.unpark(t);
    }
}

这段代码无论如何执行,JVM进程都可以正常退出,即使main线程的LockSupport.unpark(t);先于t线程的LockSupport.park();执行。

wait/notify和LockSupport对比

通过对比可以发现LockSupport相比wait/notify具有两大优势:

  • LockSupport不需要同步代码块,而wait/notify需要使用synchronized来同步代码块,同步的两个线程间也不需要维护一个共享的同步对象了,实现了线程间的解耦;
  • unpark函数可以先于park调用,所以不需要担心线程间的执行的先后顺序,而wait必须要先于notify调用;

LockSupport注意事项

  • 多次调用·unpark方法和调用一次unpark方法效果一样,例如线程A连续调用两次LockSupport.unpark(B)方法唤醒线程B,然后线程B调用两次LockSupport.park()方法, 线程B依旧会被阻塞;

参考文献

自己动手写把”锁”—LockSupport深入浅出

JUC学习 - LockSupport工具类 一、JUC中的LockSupport工具类 LockSupport位于java.util.concurrent(简称juc)包中,算是juc中一个基础类,juc中很多地方都会使用LockSupport,非常重要!!! 关于线程等待/唤醒的方法,前面的我们已经讲过2种了: 方式1:使用Object中的wait()方法让线程等待,使用Object中的notify()方法唤醒线程 方式2:使用juc包中Condition的await()方法让线程等待,使用signal()方法唤醒线程 Object和Condit 阅读详情

相关推荐

从零构建基于ZYNQ与AD9361的SDR信号源:FPGA逻辑与射频前端的协同设计

本文详细介绍了从零开始构建基于ZYNQ与AD9361的SDR信号源的完整流程。通过解析FPGA逻辑与射频前端的协同设计,重点阐述了如何利用FPGA生成基带信号,并通过ARM处理器配置AD9361,最终实现一个可编程的2.4GHz载波信号发生器。内容涵盖硬件选型、Vivado环境搭建、AXI总线通信、LVDS接口设计及软件驱动开发,为SDR开发者提供了实用的实战指南。

weixin_29200485的博客 214

JUC锁之LockSupport

LockSupport是一个线程工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞,也可以在任意位置唤醒。 它的内部其实两类主要的方法:park(停车阻塞线程)和unpark(启动唤醒线程)。

liuerchong的博客 1789

计算机视觉(相机标定;内参;外参;畸变系数)

目录 一、预备知识 1、坐标系变换过程(相机成像过程) (1)相机坐标系转换为图像坐标系(透视投影变换遵循的是针孔成像原理) (2)齐次坐标的引入原因:(为什么引入齐次坐标???) 2、内参与外参矩阵的构成 3、畸变参数 二、相机标定 1、张正友标定法(光学标定)及其求解思路 2、求解内参矩阵与外参矩阵的思路: (1)计算内参与外参矩阵的乘积M (2)求解内参矩阵A (3)求解外参矩阵(R1 R2 T) 三、参数优化 1、L-M算法 2、相机标定步骤 四、相关代码及其实验结.

QYJ_WORKHARDING的博客 6万+

【JUC基础】09. LockSupport

LockSupport是一个线程阻塞工具,可以在线程任意位置让线程阻塞。线程操作阻塞的方式其实还有Thread.suspend()和Object.wait()。而LockSupport与suspend()相比,弥补了由于resume()方法而导致线程被挂起(类似死锁)的问题,也弥补了wait()需要先获得某个对象锁的问题,也不会抛出InterruptedException异常。

有一只柴犬的专栏 1131

【信创-k8s】银河麒麟V10国防版+鲲鹏/飞腾(arm64架构)在线/离线部署k8s1.30+kubesphere

银河麒麟作为国家核高基专项的重要成果,国防版凭借其卓越的安全性和可靠性,已成为军工领域的首选操作系统。之前我们在适配麒麟V4国防版的过程中已发现诸多安全性要求,而麒麟V10国防版在安全防护等级上又达到了更高的级别。本文将主要演示离线部署,因为军工项目基本不会出现联网场景。即使在线,也可以按离线方式部署,且离线部署由于有私有仓库,不会存在镜像获取不到和丢失情况。

jiaworld的博客 730

RK356x U-Boot研究所(命令篇)3.7 pci与nvme命令的用法

RK356x U-Boot研究所(命令篇)3.7 pci与nvme命令的用法

Systemcall名屋 2084

自己动手写把”锁”---LockSupport深入浅出

本篇是《自己动手写把"锁"》系列技术铺垫的最后一个知识点。本篇主要讲解LockSupport工具类,它用来实现线程的挂起和唤醒。 LockSupport是Java6引入的一个工具类,它简单灵活,应用广泛。 一、简单 俗话说,没有比较就没有伤害。这里咱们还是通过对比来介绍LockSupport的简单。 在没有LockSupport之前,线程的挂起和唤醒咱们都是通过Object的wai...

weixin_30485799的博客 537

增量学习入门:概念、代码示例与应用场景

在当今快速变化的数据环境中,传统的机器学习模型往往需要重新训练以适应新的数据。然而,这种方法不仅耗时耗力,还可能导致模型性能的不稳定。增量学习(Incremental Learning)作为一种新兴的学习范式,能够在新数据到来时动态更新模型,而无需重新训练整个模型。本文将详细介绍增量学习的基本概念、代码示例、应用场景以及需要注意的事项。增量学习作为一种高效的机器学习方法,能够在新数据到来时动态更新模型,具有广泛的应用前景。通过本文的介绍,相信你对增量学习有了初步的了解。

加入“Super Entity”,与全能开发团队共探AI智能体与数字人项目,开启前沿技术之旅。 1152

JUC 锁之 LockSupport 详解

一 概述 今天我们来介绍 Java 并发编程系列之 LockSupport,在介绍 Synchronized 的时候我们有提过,不推荐同学们使用 Object 的 wait、notify、notifyAll 等函数做多线程间的通信协同,使用 LockSupport 会是更好的选择,本篇就来谈谈 LockSupport,也正好为下篇的 AQS(AbstractQueuedSynchronized)打基础。 二 LockSupport 概念 LockSupport 是线程工具类,主要作用是阻塞和唤醒线程,底层

liuwg1226的专栏 714

2025年前端框架全景解析:React、Vue、Angular的生态与未来之争

前端框架的竞争本质是工程哲学的分野:React的灵活、Vue的简洁、Angular的严谨,分别对应不同场景需求。

科技D人生 4844

UCIE Specification详解(二)

UCIe架构概述。

Crazzy_M的博客 3299

并发编程-LockSupport和wait&notify的区别

目录LcokSupport定义常用的方法和基本原理了解应用 LcokSupport 定义 LockSupport是一个在JUC包里的线程阻塞工具类,所有的方法都是静态方法,主要用途是让线程在任意位置阻塞,广泛应用在AQS和各种JUC的锁中 常用的方法和基本原理了解 public static void park(Object blocker); // 暂停当前线程 public static void parkNanos(Object blocker, long nanos); // 暂停当前线程,不过

weixin_39827884的博客 888

SA8295P QNX主机上电启动流程分析

嵌入式系统的启动过程对于确保系统正常运行至关重要。本文将详细分析SA8295P芯片在QNX主机上的上电启动流程,并提供相应的源代码示例。嵌入式系统的启动过程对于确保系统正常运行至关重要。本文将详细分析SA8295P芯片在QNX主机上的上电启动流程,并提供相应的源代码示例。以下是一个SA8295P QNX主机上电启动流程分析。

CodeMaven的博客 1231

JUC工具类-LockSupport概述

​ 多线程并发场景中,时常需要线程协同,故而需要对当前线程进行阻塞,并唤醒需要协同的线程来一起完成任务。​ LockSupport来自于JDK1.5,位于JUC包的locks子包,是一个非常方便实用的线程阻塞工具类,它定义了一组的公共静态方法,这些方法提供了最基本的线程阻塞和唤醒功能,可以在线程内任意位置让线程阻塞、唤醒。​在AQS框架的源码中,当需要阻塞或唤醒一个线程的时候,都会使用LockSupport工具来完成。

qq_36010886的博客 364

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

JUC锁: LockSupport详解

LockSupport是锁中的基础,是一个提供锁机制的工具类,所以先对其进行分析。

qq_63353796的博客 962

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

JUC之LockSupport与Condition

JUC之LockSupport与Condition 文章目录JUC之LockSupport与Condition一、LockSupport二、Condition1、等待队列处理2、同步队列处理三、Usage 一、LockSupport park() 阻塞当前线程 调用unpark、或者中断该线程,唤醒 unpark() 唤醒线程 这个工具主要用于对线程进行一个阻塞、唤醒处理。 二...

rekingman的博客 310

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

【JUC】LockSupport理解

await(), signal(), 和 signalAll() 的调用必须在持有相关 Lock 的同步代码块中进行。LockSupport使用了一种名为permit(许可)的概念来做到阻塞和唤醒线程的功能,每个线程都有一个许可,permit只有两个值0和1,默认是0。await(), signal(), 和 signalAll() 是 java.util.concurrent.locks.Condition 接口中的方法。中实现线程间的等待和唤醒。关键字一起使用,用于在。Unsafe类的本地方法。

weixin_45628042的博客 712

LockSupport 深度解析

AQS 是 JUC 中大多数同步器(SemaphoreFutureTask等)的基础框架。AQS 内部维护了一个虚拟的 CLH (Craig, Landin, and Hagersten) 双向队列来管理等待获取同步状态(如锁)的线程。在 AQS 中的作用:阻塞获取失败的线程: 当一个线程尝试获取同步状态失败时(例如,调用lock()但锁已被占用),AQS 会将该线程包装成一个节点(Node)加入到等待队列的尾部。然后,在将节点安全地插入队列后,AQS 会调用(这里的this。

左灯右行的爱情 1360

JUC Lock:LockSupport详解

文章目录一、LockSupport概念二、LockSupport核心源码分析1、构造函数2、核心函数分析2.1、 park函数2.2 、unpark函数三、LockSupport示例说明(通过对比说明优点)1、使用wait/notify实现线程同步2、使用park/unpark实现线程同步四、面试问题1、为什么LockSupport也是核心基础类?2、写出分别通过wait/notify和LockSupport的park/unpark实现同步?3、LockSupport.park()会释放锁资源吗? 那么Co

qq_38327769的博客 1533

JUC:LockSupport和线程中断

1. 面试题 2. 线程中断机制   2.1 简介   2.2 中断的相关API之三大方法说明   2.3 面试题   2.4 总结 3. LookSupport   3.1 三种让线程等待和唤醒的方法   3.2 面试题

2301_79526467的博客 1548

Java LockSupport以及park、unpark方法源码深度解析

介绍了JUC中的LockSupport阻塞工具以及park、unpark方法的底层原理,从Java层面深入至JVM层面。

终生学习践行者 5769

LockSupport

LockSupport LockSupport是用来创建锁和其他同步类的基本线程阻塞原语。 LockSupport中的park()和unpark()的作用分别是阻塞线程和解除阻塞线程。 3种让线程等待和唤醒的方法 使用Object中的wait()方法让线程等待,使用Object中的notify()方法唤醒线程 使用JUC包中Condition的await()方法让线程等待,使用signal()方法唤醒线程 LockSupport类可以阻塞当前线程以及唤醒指定被阻塞的线程 1. 使用Object中的w

weixin_42480780的博客 5930

【JUC】LockSupport线程等待唤醒

本文探讨了Java中线程间的等待与唤醒机制,包括传统`Object`类的`wait()`和`notify()`方法、`Condition`接口的`await()`与`signal()`方法,以及`LockSupport`类的`park()`和`unpark()`方法。通过示例代码演示了这些方法的正确使用方式及其限制,如必须在同步代码块内使用`wait()`/`notify()`,而`LockSupport`则无需锁即可操作。

我只管埋头前行,剩下的交给时间。 1080

【JUC】十六、LockSupport类实现线程等待与唤醒

先发permit,再LockSupport.park(),就像持证上岗,或者高速公路的ETC,提前缴费买了通行证后走高速,遇到关卡一路通畅,此时park形同虚设。A2:因为凭证的数量最多为1,连续调用两次unpark并不会有两个凭证,而调用两次park却要消耗两个凭证,凭证不够,不能放行。可以发现,将notify先于wait执行,等待被唤醒的线程会陷入无限等待中,就像叫你起床的人,先走了,你睡着以后没人再叫你了。A1:因为unpark后线程t获得了一个凭证,之后线程t再调用park,就凭证消费,畅通无阻。

llg___的博客 1123

JUC从实战到源码:LockSupport

在多线程编程中,线程间的协调是一个复杂而又至关重要的话题。Java提供了多种机制来实现线程间的同步和通信,以确保数据的一致性和线程的安全执行。在这些机制中,LockSupport类提供了一种高效且灵活的方式来控制线程的阻塞和唤醒。本文将深入探讨LockSupport类及其与Java中其他线程控制机制的对比,包括传统的wait和notify方法以及基于Condition的await和signal方法。我们将通过代码示例和分析,详细解释这些机制的工作原理和使用场景,以及它们之间的差异和最佳实践。

qq_43843951的博客 1190
上一篇: [NIO与Netty] ThreadLocal详解
下一篇: [JUC] AQS独占模式详解
zkp_java
博客等级 码龄15年 46粉丝 56原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值