ReentrantLock入门级

STM32巡线小车PID调参实战:从五路灰度传感器数据到稳定运行的避坑指南 本文详细介绍了STM32巡线小车的PID调参实战,从五路灰度传感器数据处理到PID参数优化,提供了系统化的调试方法和常见问题解决方案。通过加权平均法计算偏移量,逐步调整比例、积分、微分参数,实现小车稳定巡线。文章还涵盖了定时器配置、控制周期优化及高级调试技巧,帮助开发者避开常见陷阱,提升巡线性能。 阅读详情

是什么

synchronized关键词功能一致,让线程保持同步。synchronized是基于Java语法上的实现,而ReentrantLock是基于API实现,操作上相对灵活。JDK1.7 之后 两者的性能上不分秋色。ReentrantLock实现了Lock接口,我们来看看那Lock几个主要接口定义:

/**
当前线程尝试获取独占锁,如果发现锁已被其他线程占用将被挂起。
**/
void lock();

/**
同void lock() 方法类似,只不过该方法能够被线程中断。
**/
void lockInterruptibly() throws InterruptedException;

/**
当前线程调用该方法会尝试获取锁,如果获取到返回true,反之返回false,并不会阻塞该线程。
**/
boolean tryLock();
/**
同boolean tryLock()方法类似。也是尝试获取锁,在拿不到锁时会等待一定时间,等待时可以被中断。超时之后还未拿到锁返回false.
**/
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

/**
 释放锁。
**/
void unlock();

/**
 返回一个与lock实例绑定的Condition,通过调用Condition#await()方法,可以释放当前线程持有的锁并阻塞挂起。
**/
Condition newCondition();

Condition的作用主要应用于多线程的协同,下面看看Condition 接口的一些主要定义:

/**
 对于获取锁的线程,调用此方法后会阻塞直到其他线程唤醒或者线程被中断
**/
void await() throws InterruptedException;

/**
相比较await()而言,它不响应中断。
**/
void awaitUninterruptibly();
/**
唤醒因调用同一个condition实例的await() 方法 而阻塞挂起的线程
**/ 
void signal();

/**
 唤醒所有阻塞的线程
**/
void signalAll();

怎么用

ReentrantLock锁的基本使用

需求:有20个用户(线程)同时去抢购剩余的10张火车票,必须保证数据不出现混乱。具体实现如下:

TicketMachine

/**
 * 取票机
 */
public class TicketMachine {
    Lock lock = new ReentrantLock();
    /**
     * 票数量
     */
    private Integer ticketNum = 10;

    /**
     * 购买
     */
    public void buying() {
        try {
           // 1.
            lock.lock();
            if (ticketNum > 0) {
                System.out.println(Thread.currentThread().getName() + "购买了第" + ticketNum + "张票");

                ticketNum--;
            } else {
                System.out.println("已购买完,抢不到了.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
           // 2.
            lock.unlock();
        }
    }
}

运行方法

 TicketMachine ticketMachine = new TicketMachine();
        for (Integer i = 0; i < 20; i++) {
            new Thread(() -> {
                ticketMachine.buying();
            }, "同学" + (i + 1)).start();
        }

运行结果

同学1购买了第10张票
同学4购买了第9张票
同学2购买了第8张票
同学3购买了第7张票
同学5购买了第6张票
同学6购买了第5张票
同学7购买了第4张票
同学8购买了第3张票
同学9购买了第2张票
同学10购买了第1张票
已购买完,抢不到了.
已购买完,抢不到了.
已购买完,抢不到了.
已购买完,抢不到了.
已购买完,抢不到了.
已购买完,抢不到了.

上面有几处我们着重的说一下 。代码(1)处调用lock() 方法获取锁保证同一时刻只能有一个线程对变量ticketNum(票数)进行操作,不会造成脏数据的问题。代码(2)处将unlock()方法放置finally块中 确保代码执行完毕后锁能进行释放,不造成死锁。

针对此案例我们提出几个疑问

  • 若没有调用lock()方法,直接调用 unLock() 方法会出现问题么?
  • 若多次调用lock()方法,仅调用一次 unLock() 方法会出现问题么?

问题一:若无调用lock() 方法,直接执行unLock() 方法将会抛出IllegalMonitorStateException。
问题二: 会导致其他线程获取不到锁。

Lock结合Condition 的使用

需求:10个线程每次以10增量值对变量sum进行求和运算,当任何一个线程发现求和运算得出的结果等于100,将唤醒另一个线程将结果输出。

具体实现如下:

/**
 * Lock 和 Condition 配合使用案例
 */
public class LockConditionDemo {
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();
    /**
     * 总和
     */
    private Integer sum = 0;

    /**
     * 计算和
     *
     * @param count
     */
    public void calcSum(Integer count) {
        try {
            lock.lock();
            sum += count;
            //4.
            if (sum == 100) {
                condition.signal();
                System.out.println("sum 已等于 100 ,唤醒线程...");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }

    /**
     * 显示总和
     */
    public void show() {
        try {
            lock.lock();
            System.out.println("线程【"+Thread.currentThread().getName()+"】"+"等待输出sum和");
            //2.
            condition.await();

            System.out.println("线程【"+Thread.currentThread().getName()+"】"+"得出 sum = " + sum);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

运行方法:

    public static void main(String[] args) {
        LockConditionDemo t = new LockConditionDemo();
        //1.
        Thread thread = new Thread(() -> {
            t.show();
        }, "获取求和线程");
        thread.start();

        //3.
        for (Integer i = 0; i < 10; i++) {
            new Thread(() -> t.calcSum(10), "线程" + i).start();
        }

    }

输出结果:

线程【获取求和线程】等待输出sum和
sum 已等于 100 ,唤醒线程...
线程【获取求和线程】得出 sum = 100

从代码(1) 处,我们可以看出启动了一个 获取求和线程,代码(2) 处,调用了condition.await()方法,将该线程阻塞挂起,等待其他线程唤醒,代码(3) 处启动了20个 对变量sum求和的线程,紧接着代码(4)处对sum的值进行判断,如果等于100将调用 condition.signal(),唤醒因调用同一个condition实例的await() 方法 而阻塞挂起的线程。


清山绿水始于尘,博学多识贵于勤。
我有酒,你有故事吗?
微信公众号:「Java锦囊」。
欢迎一起谈天说地,聊Java。


书写技术文章是一个循序渐进的过程,所以我不能保证每句话、每行代码都是对的,但至少能保证不复制、不粘贴,每篇文章都是自己对技术的认识、细心斟酌总结出来的。乔布斯说:我们在这个星球上的时间都很短,很少有机会去做几件真正伟大的事情,同时要做得好,我必须要趁我还年轻的时候完成这些事。
其实我想说的是,我是一枚程序员,我只想在有限的时间内尽可能去沉淀我这一生中所能沉淀下来的东西

反光柱定位算法实战03:VEnus代码解析和纯反光柱定位中的可改进方向 本文深入解析了开源框架VEnus的反光柱定位与建图实现流程,包括强度提取、聚类、数据关联、位姿优化等核心模块。同时指出其三大局限:匹配质量脆弱性、单一传感器依赖和地图扩展逻辑缺失,并提出改进方向:融合里程计/IMU数据、引入图优化后端、建立动态地图维护机制。该分析为基于反光柱的定位系统优化提供了实用参考,有助于提升工业场景下的定位鲁棒性和精确性。 阅读详情

相关推荐

保姆级教学:从0搭建微信小程序SpringBoot+Vue(一)

目标:实现一个微信小程序从后端数据库MySQL获取的商品展示页。 框架:后端采用SpringBoot,前端采用Vue,数据库MySQL。 部署工具:IntelliJ IDEA 2024.2专业版+HbuilderX+Node+微信开发者工具,jdk1.8已安装

weixin_44545610的博客 4925

多线程请求后台资源,ReentrantLock锁定业务代码只执行一次

2、首先获取锁,获取不到就表示有其他线程在执行,那么会进入到else,这里设置了一个自旋去等待这个锁的释放,并且设置了一个自旋超时时间,防止大量请求消耗资源。这样就是只有一个线程在执行,其他线程等待结果就可以,异常情况暂不考虑。tryLock() 方法,能拿到锁可以直接返回true,拿不到直接返回false,还可以使用带参数的超时时间tryLock(time,timeunit) 方法,具体场景具体使用。还有 wati 和 notifyall 方案 也可以实现后台业务代码只执行一次。

beauty_魅影 624

ArcGIS Pro实战:用时空立方体分析共享单车轨迹数据(含3D可视化技巧)

本文详细介绍了在ArcGIS Pro中利用时空立方体技术分析共享单车轨迹数据的全流程。从数据预处理、构建时空立方体,到执行新兴时空热点分析,并最终实现动态3D可视化,手把手教你挖掘城市骑行活动的时空规律。文章重点解析了工具参数设置、常见报错解决方案,并提供了可复用的Python脚本,助力城市规划与交通研究者高效完成时空模式挖掘。

weixin_28323057的博客 137

ReentrantLock入门讲解

一、概述 ReentrantLock字面意思就是可重入锁(re表示重新,entrant表示进入,lock表示锁),它其实是属于JUC包(java,util.concurrent)下的一个类。在多线程环境下我们为了避免并发引发的一些问题常常会选择给可能引起并发问题的代码(临界区)加锁,说到加锁大家最熟悉的可能就是synchronized关键字,除此以外的另一个就是ReentrantLock类。ReentrantLock相比于synchronized有如下特点: 可中断 可以设置超时时间 可以设置为公平

Hi_Red_Beetle的博客 1050

使用PackStack工具自动化部署OpenStack

搭建 OpenStack 环境,每个组件的安装和配置都需要熟悉其特定的依赖关系、参数设置等,对于初学者来说容易出错。PackStack 工具通过集成一系列脚本和配置文件,便于快速搭建OpenStack练习环境。CPU:支持 Intel VT - x 或 AMD - V 硬件虚拟化技术,并且要在 BIOS 里开启此功能。内存:16GB以上存储:200GB以上可用空间(2)VMware WorkStation16.0以上版本(3)远程连接工具(如Xshell、MobaXterm)

2301_80440447的博客 4094

/lib//libclntsh.so: file format not recognized; treating as linker script

centos7.7+oracle19.3 建库过程报错:预检查都是通过的 /oracle/product/19.3.0/db_1/lib/libasmperl19.a -Wl,--no-whole-archive -lclntsh -lclntshcore -lasmclntsh19 -lhasgen19 -lskgxp19 -locr19 -lcell19 -lirc INFO: /usr/bin/ld:/home/app/oracle/product/19.3.0/db_1/li...

sqlora的专栏 9914

【Java并发】【ReentrantLock】适合初学体质的ReentrantLock入门

马上跟上主播的节奏,看看怎么使用ReentrantLock,这个比较简单,非常适合我们新人朋友奥!本文只介绍简单的使用,具体原理,主播下一篇具体研究🤗是 Java 并发包 () 中的一个类,它实现了Lock接口,提供了与关键字类似的互斥锁功能,但具有更高的灵活性和扩展性。主要特点可重入性与一样,是可重入的。这意味着同一个线程可以多次获取同一个锁,而不会导致死锁。每次获取锁后,必须相应地进行相同次数的释放。公平性支持公平锁和非公平锁。

flzjkl的博客 1091

SAP OBYC自动过账全解析:从BSX到WRX的会计科目配置指南

本文深入解析SAP OBYC自动过账功能,从BSX到WRX的会计科目配置全流程,涵盖评估分组代码、事务码和评估类等核心概念。通过实战案例展示如何实现库存变动到财务过账的自动化流转,提升企业财务数据的准确性和效率。

weixin_29239279的博客 419

ReentrantLock入门之路

ReentrantLock源码分析

ch_endong的博客 173

YOLOv8改进 | 特殊场景检测篇 | 最新的多尺度特征提取DICAM(全网独家首发,增强水下图像的质量)

本文给大家带来的最新改进机制是多尺度特征提取和通道注意力机制DICAM,深度Inception和通道注意力模块(DICAM)主要用于用于增强水下图像的质量、对比度和色偏。所提出的DICAM模型考虑了水下图像的比例退化和不均匀色偏,从而提高图像的质量。通过在两个公开的水下图像增强数据集上的广泛实验,验证了提出的模型在全参考和无参考图像质量评估指标方面。欢迎大家订阅我的专栏一起学习YOLO,购买专栏读者联系读者入群获取进阶项目文件!

Snu77的博客 2216

电动汽车远程监控与诊断软件:BMW ConnectedDrive EV远程监控二次开发_7.数据安全与隐私保护

数据加密是保护数据安全的重要手段之一。在电动汽车远程监控与诊断软件中,加密技术可以确保数据在传输过程中的安全性和完整性。常见的加密技术包括对称加密和非对称加密。

zhubeibei168的博客 884

ReentrantLock的基本使用&常用方法

下面是创建一个锁然后获取再释放的一个过程,可以看到需要调用unlock()方法释放锁,为了防止程序发生异常导致不能释放锁造成程序的死锁,一般要把释放锁的代码写在finally块中,确保锁的释放。

m0_63463465的博客 7272

【数据集7】全球人类住区层GHSL数据详解

全球人类住区层GHSL数据详解

WW、forever的博客 2253

AQS之ReentrantLock(入门级理解)

ReentrantLock: 1.可重入 2.公平锁或者非公平锁 3.手动加锁,手动释放 AQS:ReentrantLock内部维护了一个AQS队列,AQS的本质是一个双向链表。AQS中存放着排队等待锁的线程对象(Node) ReentrantLock公平锁的加锁过程 public final void acquire(int arg) { //tryAcquire(arg):尝试当前线程加锁 //acquireQueued(addWaiter(Node.EXCLUSIVE), arg)):

LianghaiBoQAQ的博客 651

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

ReentrantLock详解

ReentrantLock使用,

weixin_56738054的博客 1万+

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

简单实现ReentrantLock,详解ReentrantLock底层原理

AbstractQueuedSynchronizer类不止服务于ReentrantLock类,因此该类里面有很多跟ReentrantLock不想关的代码存在,本文将提取ReentrantLock类和AbstractQueuedSynchronizer类的核心代码进行解释说明。本文末尾将附带经过我提取的手写的ReentrantLock代码,代码上附有我对该锁的理解的注解。的核心就是类,要了解就要先了解一、AbstractQueuedSynchronizer类。

duan614的博客 1897

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

ReentrantLock面试总结

ReentrantLock面试总结

HRX98的博客 2296

ReentrantLock 底层原理

想弄懂 ReentrantLock 底层原理,这一篇就够了!包含 AQS底层原理,ReentrantLock公平锁、可重入、可打断的实现原理。

weixin_54232666的博客 4537

Java ReentrantLock

1. 锁的意义——线程同步 2. 案例——基于ReentrantLock来实现同步 public class A { public static ReentrantLock reentrantLock = new ReentrantLock(); public static void main(String[] args) { new Thread(() -> { testSync(); }, "t1").start()

weixin_35821291的博客 5102

Synchronized vs ReentrantLock

摘要: 本文比较了Java中的两种锁机制:synchronized和ReentrantLock。synchronized是JVM内置的隐式锁,基于Monitor实现,支持锁升级(偏向锁→轻量级锁→重量级锁),使用简单但功能有限。ReentrantLock是显式锁,基于AQS实现,提供更丰富的功能如可中断、公平锁等。文章详细解析了synchronized的底层原理(包括字节码指令、锁状态转换)和ReentrantLock的AQS实现机制,并区分了对象锁(实例级别)和类锁(Class级别)的概念及其应用场景。

qq_41893505的博客 1238

ReentrantLock

ReentrantLock与synchronized齐名的经典java锁,十分常用。 ReentrantLock特性: 可重入 可通过构造参数设置时公平锁还是非公平锁 需要明文释放锁,而synchronized是自动释放的 ...

Pure_Eyes的博客 3504

java的reentrantlock_JAVA中ReentrantLock详解

前言:本文解决的问题RentrantLock与Synchronized区别ReentrantLock特征ReentrantLock类的方法介绍1.什么是ReentrantLock1.1ReentrantLock 与Synchronized区别在面试中询问ReentrantLock与Synchronized区别时,一般回答都是ReentrantLockReentrantLock是JDK方法,需要手动...

weixin_39611043的博客 864

ReentrantLock的特点

一 概述 自JDK5起,Java类库中新提供了java.util.concurrent包,其中的java.util.concurrent.locks.Lock接口便成了Java的另一种全新的互斥同步手段。基于Lock接口,用户能够以非块结构(Non-Block Structured)来实现互斥同步,从而摆脱了语言特性的束缚,改为在类库层面去实现同步,这也为日后扩展出不同的调度算法,不同特征,不同性能,不同语义的各种锁。 二 ReentrantLock(重入锁) 重入锁(ReenturantLock)是

calm_encode的博客 1072
上一篇: LockSupport工具类-入门级
下一篇: ReentrantReadWriteLock入门级
yi博说
博客等级 码龄11年 20粉丝 30原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值