双非本科准备秋招(21.2)—— ReentrantLock

2024-02-09 23:20

本文主要是介绍双非本科准备秋招(21.2)—— ReentrantLock,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、vs synchronized

  • 中断
  • 可以设置超时时间
  • 可以设置为公平锁
  • 支持多个条件变量

语法

    // 获取锁reentrantLock.lock();try {// 临界区} finally {// 释放锁reentrantLock.unlock();}

二、可重入

连续三次上锁。

@Slf4j(topic = "c.test")
public class Reentrant {private static ReentrantLock lock = new ReentrantLock();public static void main(String[] args) {lock.lock();try {m1();log.debug("上锁");} finally {lock.unlock();}}public static void m1(){lock.lock();try {log.debug("上锁");m2();} finally {lock.unlock();}}public static void m2(){lock.lock();try {log.debug("上锁");} finally {lock.unlock();}}
}

可以发现,上锁都成功了。

三、可打断

        使用lockInterruptibly方法,如果无竞争那么就会获得lock锁;有有竞争会进入阻塞队列,可以被其他线程用interrupt方法打断。

@Slf4j(topic = "c.test")
public class Reentrant {private static ReentrantLock lock = new ReentrantLock();public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {log.debug("启动");try {lock.lockInterruptibly();} catch (InterruptedException e) {e.printStackTrace();log.debug("我被打断了");return;}try {log.debug("获得了锁");} finally {//释放锁lock.unlock();}}, "t1");lock.lock();t1.start();try {Thread.sleep(1000);t1.interrupt();}finally {lock.unlock();}}
}

        如果用lock方法那么是无法被打断的,会一直等待。

四、锁超时

        使用trylock方法,尝试获得锁,如果能获得锁就获得,返回true,否则返回false。

立即失败

@Slf4j(topic = "c.test")
public class Reentrant {private static ReentrantLock lock = new ReentrantLock();public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {log.debug("启动");if(!lock.tryLock()){log.debug("没获得锁!");return;}try {log.debug("获得了锁");} finally {//释放锁lock.unlock();}}, "t1");lock.lock();t1.start();try {Thread.sleep(1000);}finally {lock.unlock();}}
}

超时失败:

lock.tryLock(1, TimeUnit.SECONDS),第一个参数是数字,第二个参数是单位

@Slf4j(topic = "c.test")
public class Reentrant {private static ReentrantLock lock = new ReentrantLock();public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {log.debug("启动");try {if(!lock.tryLock(1, TimeUnit.SECONDS)){log.debug("没获得锁!");return;}}catch (InterruptedException e){e.printStackTrace();}try {log.debug("获得了锁");} finally {//释放锁lock.unlock();}}, "t1");lock.lock();t1.start();try {Thread.sleep(1000);}finally {lock.unlock();}}
}

锁超时可以用来优化哲学家问题:让Chopstick继承ReentrantLock,然后使用tryLock优化。

五、公平锁

可以加一个boolean参数,true代表公平锁,默认是不公平的。

ReentrantLock lock = new ReentrantLock(true);

但是一般不用,公平锁会降低并发度

六、条件变量

        ReentrantLock 的条件变量比 synchronized 强大之处在于,它是支持多个条件变量的。

        wait和notify的模板语法中,每次都要notifyAll,然后所有的wait线程都被唤醒,如果条件没满足,就是虚假唤醒。

        但是使用了多个条件变量,我们就不需要盲目地唤醒所有线程了。

        使用newCondition()创建一个条件变量,这个案例中模拟两个线程,一个线程需要吃苹果才能工作,一个线程需要卫生纸才能工作。

    private static ReentrantLock lock = new ReentrantLock();static Condition hasApple = lock.newCondition();static Condition hasTissue = lock.newCondition();static boolean apple = false;static boolean tissue = false;

线程1:hasApple.await();方法,可以让当前线程进入等待。

        new Thread(()->{try {lock.lock();while(!apple){try {hasApple.await();} catch (InterruptedException e) {e.printStackTrace();}}log.debug("苹果来了,开始干活");}finally {lock.unlock();}}, "APPLE").start();

还需要一个唤醒线程,这里就可以看出来条件变量的优势,只需要唤醒hasApple中的线程即可,不会导致hasTissue中的线程被虚假唤醒。

    private static void sendApple(){lock.lock();try {log.debug("送苹果来了");apple = true;hasApple.signal();}finally {lock.unlock();}}

完整代码:

@Slf4j(topic = "c.test")
public class Reentrant {private static ReentrantLock lock = new ReentrantLock();static Condition hasApple = lock.newCondition();static Condition hasTissue = lock.newCondition();static boolean apple = false;static boolean tissue = false;public static void main(String[] args) throws InterruptedException {new Thread(()->{try {lock.lock();while(!apple){try {hasApple.await();} catch (InterruptedException e) {e.printStackTrace();}}log.debug("苹果来了,开始干活");}finally {lock.unlock();}}, "APPLE").start();new Thread(()->{try {lock.lock();while(!tissue){try {hasTissue.await();} catch (InterruptedException e) {e.printStackTrace();}}log.debug("卫生纸来了,开始干活");}finally {lock.unlock();}}, "TISSUE").start();Thread.sleep(1000);sendApple();Thread.sleep(2000);sendTissue();}private static void sendApple(){lock.lock();try {log.debug("送苹果来了");apple = true;hasApple.signal();}finally {lock.unlock();}}private static void sendTissue(){lock.lock();try {log.debug("送卫生纸来了");tissue = true;hasTissue.signal();}finally {lock.unlock();}}
}

输出:

这篇关于双非本科准备秋招(21.2)—— ReentrantLock的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/695573

相关文章

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

【秋招笔试】9.07米哈游秋招改编题-三语言题解

🍭 大家好这里是 春秋招笔试突围,一起备战大厂笔试 💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 大厂实习经历 ✨ 本系列打算持续跟新 春秋招笔试题 👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸 ✨ 笔试合集传送们 -> 🧷春秋招笔试合集 🍒 本专栏已收集 100+ 套笔试题,笔试真题 会在第一时间跟新 🍄 题面描述等均已改编,如果和你笔试题看到的题面描述

Detectorn2预训练模型复现:数据准备、训练命令、日志分析与输出目录

Detectorn2预训练模型复现:数据准备、训练命令、日志分析与输出目录 在深度学习项目中,目标检测是一项重要的任务。本文将详细介绍如何使用Detectron2进行目标检测模型的复现训练,涵盖训练数据准备、训练命令、训练日志分析、训练指标以及训练输出目录的各个文件及其作用。特别地,我们将演示在训练过程中出现中断后,如何使用 resume 功能继续训练,并将我们复现的模型与Model Zoo中的

第十章 【后端】环境准备(10.4)——Vagrant

10.4 Vagrant Vagrant 官网 Vagrant 镜像仓库 下载 安装 直接 install。 设置环境变量 Vagrant 默认将镜像保存在用户文件夹的 .vagrant.d 目录下,若用户文件夹在C盘,下载的镜像文件会大量占用C盘空间。设置环境变量 VAGRANT_HOME 后,Vagrant 会将镜像保存到环境变量指定的文件夹下。

OpenStack离线Train版安装系列—2计算节点-环境准备

本系列文章包含从OpenStack离线源制作到完成OpenStack安装的全部过程。 在本系列教程中使用的OpenStack的安装版本为第20个版本Train(简称T版本),2020年5月13日,OpenStack社区发布了第21个版本Ussuri(简称U版本)。 OpenStack部署系列文章 OpenStack Victoria版 安装部署系列教程 OpenStack Ussuri版

OpenStack离线Train版安装系列—1控制节点-环境准备

本系列文章包含从OpenStack离线源制作到完成OpenStack安装的全部过程。 在本系列教程中使用的OpenStack的安装版本为第20个版本Train(简称T版本),2020年5月13日,OpenStack社区发布了第21个版本Ussuri(简称U版本)。 OpenStack部署系列文章 OpenStack Victoria版 安装部署系列教程 OpenStack Ussuri版

OpenStack镜像制作系列1—环境准备

本系列文章主要对如何制作OpenStack镜像的过程进行描述记录 CSDN:OpenStack镜像制作教程指导(全) OpenStack镜像制作系列1—环境准备 OpenStack镜像制作系列2—Windows7镜像 OpenStack镜像制作系列3—Windows10镜像 OpenStack镜像制作系列4—Windows Server2019镜像 OpenStack镜像制作

我在高职教STM32——准备HAL库工程模板(1)

新学期开学在即,又要给学生上 STM32 嵌入式课程了。这课上了多年了,一直用的都是标准库来开发,已经驾轻就熟了。人就是这样,有了自己熟悉的舒适圈,就很难做出改变,老师上课也是如此,排斥新课和不熟悉的内容。显然,STM32 的开发,HAL 库已是主流,自己其实也在使用,只不过更换库就意味着教学内容有很大变化,自己也就迟迟没有迈出调整这一步。现在,是时候做出变化了,笔者计划保持教学项

2018秋招C/C++面试题总结

博主从8月中旬开始大大小小面试了十几家公司,至今也许是告一段落吧,希望后面会有好结果,因此总结记录一些C/C++方向常见的问题。和大家一起学习! 参考了互联网的各种资源,自己尝试归类整理,谢谢~ 一、C和C++的区别是什么? C是面向过程的语言,C++是在C语言的基础上开发的一种面向对象编程语言,应用广泛。 C中函数不能进行重载,C++函数可以重载 C++在C的基础上增添类,C是一个结构

ISP面试准备2

系列文章目录 文章目录 系列文章目录前言一.如何评价图像质量?二.引起图像噪声的原因三. ISP3.1 ISP Pipeline主要模块3.1.1坏点校正(Defect Pixel Correction, DPC)3.1.2黑电平校正(Black Level Correction, BLC)3.1.3镜头校正(Lens Shading Correction, LSC)3.1.4去马赛克