ReentrantLock(可重入锁) Semaphore(信号量) CountDownLatch

目录

  • ReentrantLock(可重入锁) &Semaphore(信号量)&CountDownLatch
    • ReentrantLock(可重入锁)
    • 既然有了synchronized,为啥还要有ReentrantLock?
    • Semaphore(信号量)
    • 如何确保线程安全呢?
    • CountDownLatch

ReentrantLock(可重入锁) &Semaphore(信号量)&CountDownLatch

ReentrantLock(可重入锁)

上古时期的Java中,synchronized不够强壮,功能也不够强大,也没有各种优化

ReentrantLock就是用来实现可重入锁的选择(历史遗留)

后来synchronized变得厉害了,ReentrantLock用的少了,但是仍有一席之地

synchronized也是可重入锁

传统的锁的风格,这个对象提供了两个方法: lock unlock 这个写法,就容易引起,加了锁之后,忘记解锁了

在unlock之前,触发了return或者异常,就可能引起unlock执行不到了

正确使用ReentrantLock就需要把unlock操作放到finally中

既然有了synchronized,为啥还要有ReentrantLock?

1.ReentrantLock提供了tryLock操作

lock直接进行加锁,如果加锁不成,就要阻塞

tryLock尝试进行加锁,如果加锁不成,不阻塞,直接返回false

此处通过tryLock提供了更多的“可操作空间”

2.ReentrantLock提供了公平锁的实现

ReentrantLock提供了公平锁的实现,通过队列记录加锁线程的先后顺序

synchronized是非公平锁

遵循先来后到,就是公平

3.搭配的等待通知机制不同

对于synchronized,搭配wait/notify

对于ReentrantLock,搭配 Condition类,功能比 wait/notify略强一点

实际上绝大部分开发中,使用synchronized就够用了

Semaphore(信号量)

信号量是由迪杰斯特拉提出来的

信号量也是操作系统内部给咱们提供的一个机制

操作系统对应的API被JVM封装了下,就可以通过Java代码来调用这里的相关操作了

所谓的锁,本质上也是一种特殊的信号量,

锁,可以认为就是计数值为1的信号量

释放状态,就是1

加锁状态,就是0

对于这种非0即1的信号量,称为“二元信号量”

信号量是更广义的锁

public class ThreadDemo37 {
    public static void main(String[] args) throws InterruptedException {
        Semaphore semaphore=new Semaphore(1);
        semaphore.acquire();
        System.out.println("申请1");
        semaphore.acquire();
        System.out.println("申请2");
        semaphore.acquire();
        System.out.println("申请3");
    }
}

在这里插入图片描述

import java.util.concurrent.Semaphore;


public class ThreadDemo38 {
    public static  int count=0;
    public static void main(String[] args) throws InterruptedException {
        Semaphore semaphore=new Semaphore(1);
        Thread t1=new Thread(()->{
           for(int i=0;i<500;i++){
               try {
                   semaphore.acquire();
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
               count++;
               semaphore.release();

           }
        });
        Thread t2=new Thread(()->{
            for(int i=0;i<500;i++){
                try {
                    semaphore.acquire();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                count++;
                semaphore.release();

            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(count);
    }
}

在这里插入图片描述

如何确保线程安全呢?

1.synchronized

2.ReentrantLock

3.CAS(原子类)

4.Semaphore

semaphore也可以用来实现生产者消费者模型

定义两个信号量

一个用来表示,队列中有多少个可以被消费的元素,sem1

另一个用来表示队列中有多少个可以放置新元素的空间 ,sem2

生产一个元素,sem1.V() , sem2.P()

消费一个元素,sem1.P() , sem2.V()

CountDownLatch

针对特定场景解决问题的小工具!

比如,多线程执行一个任务,把大的任务拆分成几个部分,由每个线程分别执行

下载一个文件,可能很大,但是可以拆成多个部分,每个线程负责下载一部分,下载完成之和,最终把下载的结果拼在一起。

像多线程下载这样的场景,最终执行完成之后,要把所有内容拼在一起

这个拼必然要等到所有线程执行完成

使用CountDownLatch就可以很方便的感知到这个事情!(比你调用很多次join要更简单方便一些)

如果使用join方式,就只能使用每个线程执行一个任务

借助CountDownLatch就可以让一个线程能执行很多个任务

import java.util.Random;
import java.util.concurrent.CountDownLatch;


public class ThreadDemo39 {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch=new CountDownLatch(10);
        for(int i=0;i<10;i++){
            int id=i;
            Thread t=new Thread(()->{
                System.out.println("任务:"+id+",开始下载");
                Random random = new Random();
                // [0, 5)
                int time = (random.nextInt(5) + 1) * 1000;
                try {
                    Thread.sleep(time);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("任务:"+id+",结束下载");
                latch.countDown();

            }) ;
            t.start();
        }
        latch.await();
        System.out.println("所有下载完毕");
    }
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/923560.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

51单片机从入门到精通:理论与实践指南入门篇(二)

续51单片机从入门到精通&#xff1a;理论与实践指南&#xff08;一&#xff09;https://blog.csdn.net/speaking_me/article/details/144067372 第一篇总体给大家在&#xff08;全局&#xff09;总体上讲解了一下51单片机&#xff0c;那么接下来几天结束详细讲解&#xff0c;从…

STM32C011开发(2)----nBOOT_SEL设置

STM32C011开发----2.nBOOT_SEL设置 概述硬件准备视频教学样品申请源码下载参考程序自举模式BOOT0设置配置 nBOOT_SEL生成STM32CUBEMX串口配置LED配置堆栈设置串口重定向主循环演示 概述 STM32CubeProgrammer (STM32CubeProg) 是一款用于编程STM32产品的全功能多操作系统软件工…

基于 AI 的软件工程: 超级程序员

徐昊 《AI时代的软件工程》-极客时间课程学习总结 帮助你更好地利用 LLM 提高效率,还可以站在一个更全面的立场上,讨论如何将 LLM 引入团队或是组织。 核心观点: AI 辅助业务建模:通过将模型转化为 Mermaid 格式,将我们的模型表达为大语言模型能够理解的形式。通过添加注…

【消息序列】详解(7):剖析回环模式--设备测试的核心利器

目录 一、概述 1.1. 本地回环模式 1.2. 远程环回模式 二、本地回环模式&#xff08;Local Loopback mode&#xff09; 2.1. 步骤 1&#xff1a;主机进入本地环回模式 2.2. 本地回环测试 2.2.1. 步骤 2a&#xff1a;主机发送HCI数据包并接收环回数据 2.2.2. 步骤 2b&…

如何使用GCC手动编译stm32程序

如何不使用任何IDE&#xff08;集成开发环境&#xff09;编译stm32程序? 集成开发环境将编辑器、编译器、链接器、调试器等开发工具集成在一个统一的软件中&#xff0c;使得开发人员可以更加简单、高效地完成软件开发过程。如果我们不使用KEIL,IAR等集成开发环境&#xff0c;…

计算机网络 第4章 网络层

计算机网络 &#xff08;第八版&#xff09;谢希仁 第 4 章 网络层4.2.2 IP地址**无分类编址CIDR**IP地址的特点 4.2.3 IP地址与MAC地址4.2.4 ARP 地址解析协议4.2.5 IP数据报的格式题目2&#xff1a;IP数据报分片与重组题目&#xff1a;计算IP数据报的首部校验和(不正确未改) …

【Git】常用命令汇总

目录 一.安装及配置 1.在 Windows 上安装 2.用户信息 3.差异分析工具 二.基础 1.创建仓库 2.提交与修改 三.分支管理 1.创建分支 2.合并分支 四.远程操作 1.管理 Git 仓库中的远程仓库 2.数据的获取与推送 五.标签 1.创建轻量标签和附注标签 2.查看标签和标签信…

jvm核心组件介绍

1. 类加载器&#xff08;ClassLoader&#xff09;&#xff1a; • 想象它是一个快递员&#xff0c;负责把Java类&#xff08;.class文件&#xff09;这个“包裹”从磁盘这个“发货地”送到JVM内部这个“目的地”。类加载器确保每个类只被加载一次&#xff0c;并维护一个类的层级…

【Docker】常用命令汇总

Docker 是1个开源的应用容器引擎&#xff0c;基于Go 语言并遵从 Apache2.0 协议开源。 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&#xff0c;也可以实现虚拟化。 容器是完全使用沙箱机制&#xff0c;相…

ChatGPT如何辅助academic writing?

今天想和大家分享一篇来自《Nature》杂志的文章《Three ways ChatGPT helps me in my academic writing》&#xff0c;如果您的日常涉及到学术论文的写作&#xff08;writing&#xff09;、编辑&#xff08;editing&#xff09;或者审稿&#xff08; peer review&#xff09;&a…

对比C++,Rust在内存安全上做的努力

简介 近年来&#xff0c;越来越多的组织表示&#xff0c;如果新项目在技术选型时需要使用系统级开发语言&#xff0c;那么不要选择使用C/C这种内存不安全的系统语言&#xff0c;推荐使用内存安全的Rust作为替代。 谷歌也声称&#xff0c;Android 的安全漏洞&#xff0c;从 20…

【网络安全设备系列】12、态势感知

0x00 定义&#xff1a; 态势感知&#xff08;Situation Awareness&#xff0c;SA&#xff09;能够检测出超过20大类的云上安全风险&#xff0c;包括DDoS攻击、暴力破解、Web攻击、后门木马、僵尸主机、异常行为、漏洞攻击、命令与控制等。利用大数据分析技术&#xff0c;态势感…

UE5 slate BlankProgram独立程序系列

源码版Engine\Source\Programs\中copy BlankProgram文件夹&#xff0c;重命名为ASlateLearning&#xff0c;修改所有文件命名及内部名称。 ASlateLearning.Target.cs // Copyright Epic Games, Inc. All Rights Reserved.using UnrealBuildTool; using System.Collections.Ge…

铲屎官进,2024年宠物空气净化器十大排行,看看哪款吸毛最佳?

不知道最近换毛季&#xff0c;铲屎官们还承受的住吗&#xff1f;我家猫咪每天都在表演“天女散花”&#xff0c;家里没有一块干净的地方&#xff0c;空气中也都是堆积的浮毛&#xff0c;幸好有宠物空气净化器这种清理好物。宠物空气净化器针对宠物浮毛设计&#xff0c;可以有效…

VOLO实战:使用VOLO实现图像分类任务(二)

文章目录 训练部分导入项目使用的库设置随机因子设置全局参数图像预处理与增强读取数据设置Loss设置模型设置优化器和学习率调整策略设置混合精度&#xff0c;DP多卡&#xff0c;EMA定义训练和验证函数训练函数验证函数调用训练和验证方法 运行以及结果查看测试完整的代码 在上…

AI加持,华为全屋智能品牌升级为“鸿蒙智家”

1.传统智能家居的困境&#xff1a;从便利到繁琐 近年来&#xff0c;智能家居因其便捷性和科技感受到消费者的青睐。然而&#xff0c;随着用户需求的多样化&#xff0c;传统智能家居的弊端逐渐显现&#xff1a; 设备连接复杂&#xff0c;品牌间兼容性不足&#xff0c;用户不得不…

.NET9 - Swagger平替Scalar详解(四)

书接上回&#xff0c;上一章介绍了Swagger代替品Scalar&#xff0c;在使用中遇到不少问题&#xff0c;今天单独分享一下之前Swagger中常用的功能如何在Scalar中使用。 下面我们将围绕文档版本说明、接口分类、接口描述、参数描述、枚举类型、文件上传、JWT认证等方面详细讲解。…

Qt界面篇:QMessageBox高级用法

1、演示效果 2、用法注意 2.1 设置图标 用于显示实际图标的pixmap取决于当前的GUI样式。也可以通过设置icon pixmap属性为图标设置自定义pixmap。 QMessageBox::Icon icon(

【第二讲】Spring Boot 3.4.0 新特性详解:新的依赖管理功能

Spring Boot 3.4.0 版本引入了一些显著的改进&#xff0c;其中之一就是新的依赖管理功能。这些改进不仅提升了依赖管理的便利性和一致性&#xff0c;还增强了项目的可维护性和可扩展性。本文将详细介绍 Spring Boot 3.4.0 中新的依赖管理功能&#xff0c;提供具体的使用示例和场…

阿里发布 EchoMimicV2 :从数字脸扩展到数字人 可以通过图片+音频生成半身动画视频

EchoMimicV2 是由阿里蚂蚁集团推出的开源数字人项目&#xff0c;旨在生成高质量的数字人半身动画视频。以下是该项目的简介&#xff1a; 主要功能&#xff1a; 音频驱动的动画生成&#xff1a;EchoMimicV2 能够使用音频剪辑驱动人物的面部表情和身体动作&#xff0c;实现音频与…