当前位置: 首页 > news >正文

Java 中的 volatile和synchronized和 ReentrantLock区别讲解和案例示范

在 Java 的并发编程中,volatilesynchronizedReentrantLock 是三种常用的同步机制。每种机制都有其独特的特性、优缺点和适用场景。理解它们之间的区别以及在何种情况下使用哪种机制,对提高程序的性能和可靠性至关重要。本文将详细探讨这三种机制的特性、使用场景及示例。

1. volatile 的特性

1.1 保证可见性

volatile 修饰的变量确保所有线程都能看到变量的最新值,避免了线程间的缓存不一致问题。

示例
public class VolatileVisibility {private volatile boolean running = true;public void stop() {running = false; // 修改 running}public void execute() {while (running) {// 执行任务}}
}

在这个例子中,running 变量被声明为 volatile,当一个线程调用 stop() 方法时,其他线程会立即看到 running 的值为 false

1.2 禁止指令重排序

volatile 还保证了对该变量的操作不会被重排序,从而确保程序执行的顺序性。

示例
public class VolatileReordering {private int a = 0;private volatile int b = 0;public void method1() {a = 1; // 1b = 2; // 2}public void method2() {if (b == 2) { // 3System.out.println(a); // 4}}
}

如果没有 volatile,可能会发生重排序,使得 method2()method1()b = 2 之前执行,导致 a 的值可能为 0。

1.3 不保证原子性

volatile 不能保证对复合操作的原子性,比如自增操作。

示例
public class VolatileAtomicity {private volatile int count = 0;public void increment() {count++; // 非原子操作}public int getCount() {return count;}
}

在这个例子中,increment() 方法对 count 的自增不是原子操作,可能导致数据不一致。

2. synchronized 的特性

2.1 可重入性

synchronized 允许同一线程多次获得同一把锁,而不会发生死锁。

示例
public class SynchronizedReentrancy {public synchronized void method1() {method2(); // 允许重入}public synchronized void method2() {// 执行任务}
}

在这个例子中,method1() 可以安全地调用 method2(),因为 synchronized 允许可重入。

2.2 不可中断性

synchronized 的获取锁是不可中断的,线程在等待锁时不能被中断。

示例
public class SynchronizedInterruptibility {public synchronized void lockedMethod() throws InterruptedException {Thread.sleep(10000); // 模拟长时间执行}public void execute() {Thread thread = new Thread(() -> {try {lockedMethod();} catch (InterruptedException e) {// 处理被中断}});thread.start();thread.interrupt(); // 线程在等待锁时被中断}
}

在这个例子中,lockedMethod() 无法被中断,导致线程无法释放锁。

2.3 锁的升级和降级

synchronized 支持锁的升级和降级。在方法中直接使用 synchronized,在代码块中也可以使用。

示例
public class SynchronizedUpgrade {public synchronized void method() {// 持有对象锁synchronized (this) {// 持有同一把锁}}
}

在这个例子中,使用了对象的锁和类的锁,展示了锁的升级和降级。

2.4 不公平性

synchronized 不保证公平性,可能导致某些线程长时间等待。

示例
public class SynchronizedFairness {public synchronized void method() {// 执行任务}
}

在这个例子中,多个线程访问 method() 时,无法保证先请求的线程先获得锁。

2.5 可见性、原子性和有序性

synchronized 保证了对共享变量的可见性、原子性和有序性。

示例
public class SynchronizedVisibility {private int data;public synchronized void updateData(int value) {data = value; // 更新数据}public synchronized int readData() {return data; // 读取数据}
}

在这个例子中,updateData()readData() 方法保证了 data 的线程安全。

3. ReentrantLock 的特性

3.1 可重入性

ReentrantLock 允许同一线程多次获得锁,支持可重入。

示例
public class ReentrantLockReentrancy {private final ReentrantLock lock = new ReentrantLock();public void method() {lock.lock();try {method(); // 允许重入} finally {lock.unlock();}}
}

在这个例子中,method() 方法可以安全地调用自身,因为 ReentrantLock 允许可重入。

3.2 可中断性

ReentrantLock 允许在等待锁时被中断,提供了更好的控制。

示例
public class ReentrantLockInterruptibility {private final ReentrantLock lock = new ReentrantLock();public void lockedMethod() throws InterruptedException {lock.lockInterruptibly(); // 可中断的锁try {// 执行任务} finally {lock.unlock();}}
}

在这个例子中,lockedMethod() 可以被中断,提供了更好的控制。

3.3 公平性和非公平性

ReentrantLock 支持公平和非公平锁的选择。

示例
ReentrantLock fairLock = new ReentrantLock(true); // 公平锁
ReentrantLock unfairLock = new ReentrantLock(); // 非公平锁

在这个例子中,公平锁会按照线程请求的顺序来获取锁,而非公平锁则可能导致某些线程饥饿。

3.4 条件变量

ReentrantLock 提供了条件变量支持,可以实现复杂的线程间协作。

示例
public class ReentrantLockCondition {private final ReentrantLock lock = new ReentrantLock();private final Condition condition = lock.newCondition();public void await() throws InterruptedException {lock.lock();try {condition.await(); // 等待条件} finally {lock.unlock();}}public void signal() {lock.lock();try {condition.signal(); // 唤醒等待的线程} finally {lock.unlock();}}
}

在这个例子中,使用条件变量实现了线程间的协作。

4. 三者之间的区别

特性volatilesynchronizedReentrantLock
可见性保证可见性保证可见性保证可见性
互斥性不保证保证互斥性保证互斥性
是否可重入不适用支持可重入支持可重入
代码块范围只能用于变量代码块或方法代码块或方法
锁的获取方式自动获取显式获取
公平性支持公平性
性能性能开销小性能开销中等性能开销较大

5. 适用场景分析

5.1 何时使用 volatile

适用场景:当需要保证某个变量的可见性,但不需要互斥访问时,使用 volatile 是最佳选择。

示例
public class VolatileFlag {private volatile boolean flag = true;public void stop() {flag = false;}public void run() {while (flag) {// 执行任务}}
}

在这个场景中,volatile 可以有效地减少上下文切换,提高性能。

5.2 何时使用 synchronized

适用场景:当需要对共享资源进行互斥访问时,使用 synchronized 是最佳选择。

示例
public class SynchronizedCounter {private int count = 0;public synchronized void increment() {count++;}public synchronized int getCount() {return count;}
}

在这个例子中,synchronized 确保了 count 的线程安全。

5.3 何时使用 ReentrantLock

适用场景:当需要更加灵活的锁定机制,比如可重入性、公平性或可中断的锁时,使用 ReentrantLock 是最佳选择。

示例
public class ReentrantLockCounter {private final ReentrantLock lock = new ReentrantLock();private int count = 0;public void increment() {lock.lock();try {count++;} finally {lock.unlock();}}public int getCount() {return count;}
}

在这个例子中,ReentrantLock 允许灵活的控制锁的获取和释放。

6. 总结

通过本文对 volatilesynchronizedReentrantLock 的深入分析,读者可以了解到它们各自的特性、优缺点及适用场景。在并发编程中,选择合适的同步机制不仅可以提高程序性能,还能有效地避免潜在的线程安全问题。

在实际开发中,根据不同的需求和场景,合理使用这三种机制,可以使得 Java 程序在并发执行时更加高效和安全。

相关文章:

Java 中的 volatile和synchronized和 ReentrantLock区别讲解和案例示范

在 Java 的并发编程中,volatile、synchronized 和 ReentrantLock 是三种常用的同步机制。每种机制都有其独特的特性、优缺点和适用场景。理解它们之间的区别以及在何种情况下使用哪种机制,对提高程序的性能和可靠性至关重要。本文将详细探讨这三种机制的…...

从GDAL中 读取遥感影像的信息

从GDAL提供的实用程序来看,很多程序的后缀都是 .py ,这充分地说明了Python语言在GDAL的开发中得到了广泛的应用。 1. 打开已有的GeoTIF文件 下面我们试着读取一个GeoTiff文件的信息。第一步就是打开一个数据集。 >>> from osgeo import gdal…...

算法闭关修炼百题计划(一)

多看优秀的代码一定没有错,此篇博客属于个人学习记录 1.两数之和2.前k个高频元素3.只出现一次的数字4.数组的度5.最佳观光组合6.整数反转7.缺失的第一个正数8.字符串中最多数目的子序列9.k个一组翻转链表10.反转链表II11. 公司命名12.合并区间13.快速排序14.数字中的…...

vue3实现打字机的效果,可以换行

之前看了很多文章,效果是实现了,就是没有自动换行的效果,参考了文章写了一个,先上个效果图,卡顿是因为模仿了卡顿的效果,还是很丝滑的 目录 效果图:代码如下 效果图: ![请添加图片描述](https://i-blog.csdnimg.cn/direct/d8ef33d83dd3441a87d6d033d9e7cafa.gif 代码如下 原…...

【如何学习操作系统】——学会学习的艺术

🐟作者简介:一名大三在校生,喜欢编程🪴 🐡🐙个人主页🥇:Aic山鱼 🐠WeChat:z7010cyy 🦈系列专栏:🏞️ 前端-JS基础专栏✨前…...

stm32 flash无法擦除

通过bushound调试代码发现,当上位机发送命令到模组后flash将不能擦除,通过 HAL_FLASH_GetError()函数查找原因是FLASH Programming Sequence error(编程顺序错误),解决办法是在解锁后清零标志位…...

Android—ANR日志分析

获取ANR日志: ANR路径:/data/anrADB指令:adb bugreport D:\bugrep.zip ANR日志分析步骤: “main” prio:主线程状态beginning of crash:搜索 crash 相关信息CPU usage from:搜索 cpu 使用信息…...

9.29 LeetCode 3304、3300、3301

思路: ⭐进行无限次操作,但是 k 的取值小于 500 ,所以当 word 的长度大于 500 时就可以停止操作进行取值了 如果字符为 ‘z’ ,单独处理使其变为 ‘a’ 得到得到操作后的新字符串,和原字符串拼接 class Solution { …...

近万字深入讲解iOS常见锁及线程安全

什么是锁? 在程序中,当多个任务(或线程)同时访问同一个资源时,比如多个操作同时修改一份数据,可能会导致数据不一致。这时候,我们需要“锁”来确保同一时间只有一个任务能够操作这个数据&#…...

linux创建固定大小的文件夹用于测试

在linux上创建固定大小的文件夹用于测试磁盘空间不足时的应用故障。 实验环境为centos7,有两种简易方法: 一、使用ramdisk 1、创建文件夹 mkdir /var/mytest 2、创建一个1m大小的临时文件 mount none /var/mytest -t tmpfs -o size1m size也可以写…...

大模型学习路线:这会是你见过最全最新的大模型学习路线【2024最新】

大模型学习路线 建议先从主流的Llama开始,然后选用中文的Qwen/Baichuan/ChatGLM,先快速上手体验prompt工程,然后再学习其架构,跑微调脚本 如果要深入学习,建议再按以下步骤,从更基础的GPT和BERT学起&…...

了解云计算工作负载保护的重要性,确保数据和应用程序安全

云计算de小白 云计算技术的快速发展使数据和应用程序安全成为一种关键需求,而不仅仅是一种偏好。随着越来越多的客户公司将业务迁移到云端,保护他们的云工作负载(指所有部署的应用程序和服务)变得越来越重要。云工作负载保护&…...

Swagger3基本使用

Swagger 课程目标 Swagger简介【了解】 Springboot整合swagger【掌握】 Swagger 常用注解【掌握】 knife4j-Swagger【会用】 一、Swagger3简介 Swagger 是一系列 RESTful API 的工具,通过 Swagger 可以获得项目的⼀种交互式文档,客户端 SDK 的自 动…...

如何借助Java批量操作Excel文件?

最新技术资源(建议收藏) https://www.grapecity.com.cn/resources/ 前言 | 问题背景 在操作Excel的场景中,通常会有一些针对Excel的批量操作,批量的意思一般有两种: 对批量的Excel文件进行操作。如导入多个Excel文件…...

JUC并发编程_Lock锁

JUC并发编程_Lock锁 1、Lock锁介绍2、主要方法3、与 synchronized 的区别4、Condition 使用示例 1、Lock锁介绍 Java中的 Lock 锁是 java.util.concurrent.locks 包下的一个接口,它提供了比 synchronized 关键字更灵活的锁定机制。 2、主要方法 lock()&#xff1a…...

Unity中的功能解释(数学位置相关和事件)

向量计算 Vector3.Slerp(起点坐标,终点坐标,t),可是从起点坐标以一个圆形轨迹到终点坐标,有那么多条轨迹,那怎么办 Vector3.Slerp 进行的是沿球面插值,因此并不是沿着严格的“圆形…...

ElementPlus---Timeline 时间线组件使用示例

介绍 使用ElementPlus时间线组件在后台首页实现通知公告列表展示&#xff0c;使用Vue3开发。 实现代码 Vue3代码 <el-timeline><el-timeline-itemstyle"max-width: 600px"v-for"(activity, index) in activities":key"index":times…...

推荐4款2024年大家都在用的高质量翻译器。

翻译器在我们的生活中有着很重要的作用&#xff0c;不管是我们在学习还是工作&#xff0c;生活娱乐&#xff0c;出国旅游等场合都会派上用场&#xff0c;它是我们解决沟通的障碍&#xff0c;提高阅读效率的好帮手。我自己使用的翻译器有很多&#xff0c;可以给大家列举几款特别…...

Mybatis 返回 Map 对象

一、场景介绍 假设有如下一张学生表&#xff1a; CREATE TABLE student (id int NOT NULL AUTO_INCREMENT COMMENT 主键,name varchar(100) NOT NULL COMMENT 姓名,gender varchar(10) NOT NULL COMMENT 性别,grade int NOT NULL COMMENT 年级,PRIMARY KEY (id) ) ENGINEInnoD…...

Vue3(三)路由基本使用、工作模式(history,hash)、query传参和param传参、props配置、编程式路由导航

文章目录 一、路由的基本使用二、路由器的工作模式三、RouterLink中to的两种写法四、嵌套路由五、路由传参1. query传参2. params传参 六、路由的propos配置七、编程式路由导航 一、路由的基本使用 安装&#xff1a;npm i vue-router 在src/pages文件下&#xff0c;创建三个路…...

PyInstaller打包的EXE程序修改与反编译

PyInstaller打包的EXE程序修改与反编译完全指南 前言 在实际工作中&#xff0c;我们经常会遇到需要修改已打包的Python EXE程序的情况——可能是界面文字需要调整&#xff0c;也可能是功能需要微调。本文将系统介绍如何对PyInstaller打包的EXE程序进行反编译、修改和重新打包&a…...

New-API数据导出功能:轻松管理AI模型使用记录与账单数据

New-API数据导出功能&#xff1a;轻松管理AI模型使用记录与账单数据 【免费下载链接】new-api A unified AI model hub for aggregation & distribution. It supports cross-converting various LLMs into OpenAI-compatible, Claude-compatible, or Gemini-compatible for…...

uni-number-box深度解析:从基础属性到高级双向绑定实战

1. uni-number-box基础入门&#xff1a;从零开始玩转数字输入框 第一次接触uni-number-box时&#xff0c;我也觉得这不就是个简单的数字加减控件吗&#xff1f;直到在电商项目中真正用起来&#xff0c;才发现这个看似简单的组件藏着不少门道。uni-number-box是uni-app框架提供的…...

喜马拉雅音频下载终极指南:如何永久保存付费专辑到本地

喜马拉雅音频下载终极指南&#xff1a;如何永久保存付费专辑到本地 【免费下载链接】xmly-downloader-qt5 喜马拉雅FM专辑下载器. 支持VIP与付费专辑. 使用GoQt5编写(Not Qt Binding). 项目地址: https://gitcode.com/gh_mirrors/xm/xmly-downloader-qt5 还在为喜马拉雅…...

从通信原理到Verilog:一个约束长度7的卷积码编码器是如何炼成的?

从通信原理到Verilog&#xff1a;一个约束长度7的卷积码编码器是如何炼成的&#xff1f; 在数字通信系统的设计中&#xff0c;纠错编码技术如同隐形的守护者&#xff0c;确保数据在嘈杂信道中可靠传输。卷积码因其优异的纠错性能和简洁的编码结构&#xff0c;成为卫星通信、深空…...

从ITF到DSPF:华大九天Empyrean RCExplorer在版图寄生分析中的实战解析

1. 初识华大九天Empyrean RCExplorer 第一次接触华大九天的RCExplorer工具时&#xff0c;我正为一个复杂的模拟电路版图发愁。当时遇到的问题是&#xff1a;在完成版图后仿真时&#xff0c;发现关键路径的时序总是不达标&#xff0c;反复修改版图布局却始终找不到症结所在。直到…...

Linux I2C设备驱动避坑指南:以MPU6050为例,解决i2c_transfer返回EIO错误

Linux I2C设备驱动深度排障&#xff1a;MPU6050的EIO错误全解析 调试嵌入式设备时&#xff0c;最令人沮丧的莫过于那些间歇性出现的错误。它们像幽灵一样时隐时现&#xff0c;让开发者陷入无尽的猜测和试错循环。MPU6050作为一款广泛使用的运动传感器&#xff0c;其I2C接口的稳…...

RPG Maker MV终极插件合集:100+免费插件打造专业级游戏体验

RPG Maker MV终极插件合集&#xff1a;100免费插件打造专业级游戏体验 【免费下载链接】RPGMakerMV RPGツクールMV、MZで動作するプラグインです。 项目地址: https://gitcode.com/gh_mirrors/rp/RPGMakerMV 你是否曾经为RPG Maker MV的功能限制感到困扰&#xff1f;想要…...

从皮肤色素基因到育种选择:Fst值在动植物研究中的实战解读指南

从皮肤色素基因到育种选择&#xff1a;Fst值在动植物研究中的实战解读指南 当我们在玉米田里观察不同品种的株高差异&#xff0c;或比较藏猪与大白猪的肉质特性时&#xff0c;本质上都在探索同一个问题&#xff1a;群体间的遗传分化如何塑造了这些表型多样性&#xff1f;Fst值作…...

AMBA 3 AXI协议架构解析与工程实践

1. AMBA 3 AXI协议架构解析AMBA 3 AXI协议作为ARM推出的第三代高级可扩展接口&#xff0c;其架构设计充分考虑了现代SoC对高带宽和低延迟的核心需求。与传统的AMBA 2 AHB协议相比&#xff0c;AXI通过五项关键技术革新实现了性能的质的飞跃&#xff1a;1.1 五通道分离式架构AXI协…...