Java 多线程之 synchronized (互拆锁/排他锁/非观锁)
文章目录
- 一、概述
- 二、使用方法
- 三、测试示例
一、概述
-
在Java中,synchronized 关键字用于实现线程之间的同步。提供了一种简单而强大的机制来控制多个线程之间的并发访问,确保共享资源的安全性和一致性。它解决了多线程环境中的竞态条件、数据竞争和内存模型等问题,是实现线程安全的重要手段之一。它主要有以下几个作用:
- 互斥性(Mutual Exclusion):synchronized 用于实现互斥访问,确保同一时间只有一个线程可以进入被 synchronized 修饰的代码块或方法。当一个线程获取了锁(也称为监视器锁)后,其他线程就无法进入该代码块或方法,直到锁被释放。
- 可见性(Visibility):synchronized 不仅保证了互斥性,还保证了对共享变量的修改对其他线程是可见的。当一个线程释放锁时,它会将对共享变量的修改刷新到主内存,而其他线程在获取锁之前会从主内存中重新读取共享变量的值,确保了线程之间的可见性。相应的 volatile 关键字也有这个功能,请看 volatile 的使用说明。
- 有序性(Ordering):synchronized 保证了代码的执行顺序按照线程的获取锁的顺序来进行。即使在多个线程之间存在指令重排序,通过 synchronized 的释放和获取锁操作,可以确保代码块内的操作按照顺序执行。
- 内存屏障(Memory Barriers):synchronized 的进入和退出操作都会插入内存屏障,这些屏障会阻止指令重排序和确保内存的可见性。这种特性使得 synchronized 不仅仅是一种同步机制,还可以作为一种内存屏障来确保指令的有序执行。
- 可重入性:可重入性是由内置锁(synchronized)和可重入锁(ReentrantLock)实现的。当一个线程已经获得了一个锁,并且在持有锁的代码块或方法中再次请求同一个锁时,它可以直接通过,而不会被阻塞。这样的机制称为可重入锁(Reentrant Locking)或递归锁(Recursive Locking)。
-
synchronized 是 Java 中用于实现内置锁(Intrinsic Lock)或监视器锁(Monitor Lock)的关键字,它属于独占锁(Exclusive Lock)或互斥锁(Mutual Exclusion Lock)。
-
使用时有以下几点注意
- synchronized 锁的是对象。
- 不建议使用String、Integer、Long等常量作为锁的对象。因这样的锁是全局的,如果多个线程中使用了相同的锁,会导致全部阻塞。
- 属于升级锁,由无锁、轻量级锁(偏向锁、自旋锁)到重量级锁根据情况自动升级。
- synchronized 可以修饰方法,也可以修饰代码块。
二、使用方法
-
作用在代码上,相当于给代码块加锁(Lock)
public void performTask() {// synchronized 作用于代码块synchronized (lock) {// 业务逻辑,同步代码块,对共享资源进行操作}} -
作用在方法上,相当于给整个方法加锁(Lock)
// synchronized 作用在方法上public synchronized void increment() {// 业务逻辑,同步代码块,对共享资源进行操作}
三、测试示例
-
一个会出异常的示例
- 在下面这个测试示例中有一个 Counter 类,在这个类中有一个 add 方法,当记数 count 小于 50000 时自增。然后在 main 方法中启动100个线程来同时进行增加操作,由于没有加锁(synchronized),最后结果总是会大于 50000。
package top.yiqifu.study.p004_thread;import java.io.File; import java.util.ArrayList; import java.util.List;public class Test061_ThreadSynchronized {public static class Counter {private volatile int count = 0;public void increment() {count++;}public int getCount() {return count;}public void add(){if(this.getCount() < 50000){// Thread.yield();File.listRoots();// 模拟复杂业务,执行一些额外的语句this.increment();}}}public static void main(String[] args) {Counter counter = new Counter();List<Thread> threads = new ArrayList<>();for(int count = 0; count < 100; count++) {Thread thread = new Thread(() -> {for (int i = 0; i < 1000; i++) {counter.add();}});threads.add(thread);}for(Thread t : threads) {t.start();}for(Thread t : threads) {try {t.join();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("最后结果: " + counter.getCount());}} -
修改正示例
-
要解决这个问题,可以使用 synchronized 关键字来对代码块加锁。
-
在代码块上加 synchronized 关键字
public void add(){synchronized(this) {if(this.getCount() < 50000){File.listRoots();// 模拟复杂业务,执行一些额外的语句this.increment();}}} -
在 add 方法上加 synchronized 关键字
public synchronized void add(){if(this.getCount() < 50000){File.listRoots();// 模拟复杂业务,执行一些额外的语句this.increment();}}
-
相关文章:
Java 多线程之 synchronized (互拆锁/排他锁/非观锁)
文章目录 一、概述二、使用方法三、测试示例 一、概述 在Java中,synchronized 关键字用于实现线程之间的同步。提供了一种简单而强大的机制来控制多个线程之间的并发访问,确保共享资源的安全性和一致性。它解决了多线程环境中的竞态条件、数据竞争和内存…...
开源vs闭源大模型如何塑造技术的未来?开源模型的优劣势未来发展方向
开源vs闭源大模型如何塑造技术的未来?开源模型的优劣势&未来发展方向 写在最前面一、开源与闭源:定义与历史背景开源和闭源的定义开源大模型:社区驱动的创新 二、开源和闭源的优劣势比较开源大模型(瓶颈)数据&…...
如何使用无代码系统搭建软件平台?有哪些开源无代码开发平台?
无代码是什么 无代码开发,也称为零代码(Zero Code)开发,是一种技术概念。无代码开发无需代码基础,适合业务人员、IT开发及其他各类人员使用。他们通过无代码开发平台快速构建应用,并适应各种需求变化&#…...
微信怎么设置自动回复?
自动回复的用处 微信自动回复可以提高沟通效率。当你无法立即回复消息时,设置自动回复可以让对方知道你的情况,并且不会因为长时间没有回复而产生误解或不满。 微信自动回复可以节省时间和精力。如果你经常收到类似的询问或回复,通过设置自动…...
基于Vue3的低代码开发平台——JNPF
目录 一、什么是Vue.js ? 二、Jnpf-Web-Vue3 的技术栈介绍 (1)Vue3.x (2)Vue-router4.x (3)Vite4.x (4)Ant-Design-Vue3.x (5)TypeScript &#x…...
Thinkphp6 模型 指定字段自增的方法
tp6要使用Db类必须使用门面方式(think\facade\Db)调用。 use think\facade\Db; 然后,用Db::raw就可以实现指定字段自增了。...
WhatsApp开发客户攻略来袭!还有你不知道的账号解封秘籍!
别人用 WhatsApp 都是订单多到爆单,自己用 WhatsApp 却是订单、客户寥寥无几甚至账号被封?想必外贸从业者在用 WhatsApp 开发客户的时候都有这样的烦恼,今天这篇文章就和大家聊一聊怎么用 WhatsApp 高效地开发客户。 WhatsApp 开发客户的优势…...
Linux C 基于tcp多线程在线聊天室
多线程在线聊天室 概述客户端服务端 概述 客户端实现了判单用户登录结果、防止单回车字符发送、保存和显示历史聊天记录(仅自己)、退出聊天室功能。 服务端实现了验证用户是否已经存在(支持最大64用户连接)支持广播用户进入退…...
代码随想录算法训练营第23期day60|84.柱状图中最大的矩形
一、84.柱状图中最大的矩形 力扣题目链接 42接雨水 是找每个柱子左右两边第一个大于该柱子高度的柱子,而本题是找每个柱子左右两边第一个小于该柱子的柱子。 本题是要找每个柱子左右两边第一个小于该柱子的柱子,所以从栈头(元素从栈头弹出…...
vue动态获取目录结构进行配置静态路由
文章目录 前言定义项目页面格式一、vite 配置动态路由新建 /router/utils.ts引入 /router/utils.ts 二、webpack 配置动态路由总结如有启发,可点赞收藏哟~ 前言 项目中动态配置路由可以减少路由配置时间,并可减少配置路由出现的一些奇奇怪怪的问题 路由…...
产品工程师工作的职责十篇(合集)
一、岗位职责的作用意义 1.可以最大限度地实现劳动用工的科学配置; 2.有效地防止因职务重叠而发生的工作扯皮现象; 3.提高内部竞争活力,更好地发现和使用人才; 4.组织考核的依据; 5.提高工作效率和工作质量; 6.规范操作行为; 7.减少违章行为和违章事故的发生…...
图片降噪软件 Topaz DeNoise AI mac中文版功能
Topaz DeNoise AI for Mac是一款专业的Mac图片降噪软件。如果你有噪点的相片,可以通过AI智能的方式来处理掉噪点,让照片的噪点降到最 低。有了Topaz DeNoise AI mac版处理图片更方便,更简单。 Topaz DeNoise AI mac软件功能 无任何预约即可在…...
【开源】基于Vue.js的车险自助理赔系统的设计和实现
项目编号: S 018 ,文末获取源码。 \color{red}{项目编号:S018,文末获取源码。} 项目编号:S018,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 角色管理模块2.3 车…...
2023年亚太杯数学建模思路 - 案例:粒子群算法
文章目录 1 什么是粒子群算法?2 举个例子3 还是一个例子算法流程算法实现建模资料 # 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 什么是粒子群算法? 粒子群算法(Pa…...
Android:Google三方库之Firebase集成详细步骤(一)
前提条件 安装最新版本的 Android Studio,或更新为最新版本。使用您的 Google 账号登录 Firebase请注意,依赖于 Google Play 服务的 Firebase SDK 要求设备或模拟器上必须安装 Google Play 服务 将Firebase添加到应用: 方式:使用…...
企业如何选择一款高效的ETL工具
企业如何选择一款高效的ETL工具? 在企业发展至一定规模后,构建数据仓库(Data Warehouse)和商业智能(BI)系统成为重要举措。在这个过程中,选择一款易于使用且功能强大的ETL平台至关重要,因为数…...
vr编辑器可以解决教育教学中的哪些问题
VR编辑器是一种基于虚拟现实技术的教育内容编辑器,可以帮助教师快速创建出高质量的虚拟现实教学内容。 比如在畜牧教学类,通过这个软件,教师可以将真实的动物场景、行为和特征模拟到虚拟现实环境中,让学生在沉浸式的体验中学习动物…...
国外聊天IM — Sendbird
接⼝⽂档: https://sendbird.com/docs 好久没写文章了 我在官网找到的pom, 下载不下来,git下载下来,打进项目里不能用,就只能用简单的http了 直接上代码,只是简单的调通代码,根据你自己业务改:…...
Django与Ajax
目录 一、什么是Ajax 二、Ajax引入 案例 小结 三、前后端数据传输的编码格式(contentType) 【1】form表单 【2】编码格式 【3】Ajax 【4】代码演示 四、Ajax发送JSON格式数据 【1】引入 【2】后端 【3】总结 五、Ajax提交文件数据 【发送文件数据的格式】 【结…...
linux日志不循环问题诊断
有一台Linux虚拟机的messages日志文件自2023年7月下旬开始没有按周为周期重新生成新的日志,一直累积在同一个messages文件中,如下所示: [root logrotate.d]# ls -l /var/log|grep me -rw-r--r-- 1 root root 107170 Nov 15 1…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
