java的无锁编程和锁机制
Java 的并发编程中,为了保证线程安全和高性能,采用了两种主要的同步手段:锁机制和无锁编程。以下是对锁机制、无锁编程、死锁及其避免的详细讲解。
一、无锁编程
无锁编程通过原子操作来避免传统锁,从而减少线程的上下文切换,提升性能。在 Java 中,通常使用 java.util.concurrent.atomic
包中的类来实现无锁操作。
1.1. 无锁编程的核心:CAS(Compare-And-Swap)
CAS 是无锁编程的核心机制,用来实现原子性更新。CAS 操作有三个参数:
- V:内存地址的变量值
- E:期望值
- N:新值
在进行 CAS 操作时,如果 V == E
,则 V
更新为 N
,如果不相等,表示有其他线程在操作这个值,操作失败。这样实现了原子性更新。
1.2. Java 中的无锁实现
-
原子变量:Java 提供了一些原子类,如
AtomicInteger
、AtomicLong
、AtomicReference
,它们通过底层的 CAS 实现来保证原子性。AtomicInteger atomicInteger = new AtomicInteger(0); atomicInteger.incrementAndGet(); // 原子性递增
-
自旋锁:通过不断循环检查某个条件来决定是否进入临界区。
CAS
属于一种自旋锁。Java 的ReentrantLock
提供tryLock
方法来实现非阻塞的加锁逻辑。 -
无锁集合:Java 提供了
ConcurrentLinkedQueue
、ConcurrentLinkedDeque
等无锁集合类,这些类基于 CAS 操作设计,支持高并发环境下的操作。
1.3. 无锁编程的优缺点
-
优点:
- 避免线程阻塞,减少上下文切换。
- 性能高,适合高并发环境。
-
缺点:
- 逻辑复杂,CAS 循环可能导致高开销。
- ABA 问题:CAS 判断时,如果变量的值由 A 变为 B,再变回 A,会误判未变化。Java 使用
AtomicStampedReference
来解决 ABA 问题。
二、锁机制详解和分类
Java 提供了多种锁机制,以 synchronized
和 ReentrantLock
为代表。锁机制分为多种类型,根据其特性可分为以下几类。
2.1 锁的分类
-
可重入锁(Reentrant Lock)
- 概念:允许同一线程在持有锁的情况下多次获得该锁。Java 中的
synchronized
和ReentrantLock
都是可重入锁。 - 实现:维护一个计数器记录同一线程重复获得锁的次数,解锁时减少计数,直至计数为零时释放锁。
- 优点:防止死锁,允许递归调用。
- 概念:允许同一线程在持有锁的情况下多次获得该锁。Java 中的
-
公平锁和非公平锁
- 公平锁:多个线程按照请求锁的顺序获得锁。
ReentrantLock
可以通过构造函数设置为公平锁。 - 非公平锁:线程获取锁的顺序不固定,可能出现“插队”,有时提高性能。
synchronized
和ReentrantLock
默认是非公平锁。 - 优缺点:公平锁保证了请求的顺序,避免了线程饥饿;非公平锁在高并发场景下能减少上下文切换,性能更高。
- 公平锁:多个线程按照请求锁的顺序获得锁。
-
独占锁和共享锁
- 独占锁:一次只能被一个线程持有,
synchronized
和ReentrantLock
是独占锁的典型代表。 - 共享锁:多个线程可以共享该锁,如
ReadWriteLock
,允许多个读线程同时访问,但写线程独占。 - 使用场景:共享锁适合读多写少的场景,避免独占锁的性能瓶颈。
- 独占锁:一次只能被一个线程持有,
-
悲观锁和乐观锁
- 悲观锁:认为每次操作都会引起冲突,因此上锁以避免冲突,
synchronized
和ReentrantLock
都是悲观锁。 - 乐观锁:假设冲突很少发生,因此不加锁,而是通过 CAS 来检测冲突,重试直到成功。这种机制用于无锁编程。
- 使用场景:乐观锁适用于读多写少的场景,悲观锁适合冲突频繁的场景。
- 悲观锁:认为每次操作都会引起冲突,因此上锁以避免冲突,
-
自旋锁
- 概念:线程获取锁时不会立即阻塞,而是采用“忙等”方式尝试获取锁。
- 优点:减少线程挂起和恢复的开销,但会消耗 CPU 资源。
- 使用场景:适用于锁等待时间短的情况,如 CAS 自旋机制。
2.2 锁的实现示例
synchronized
:Java 内置关键字,简单易用,具有可重入性。由 JVM 实现,不支持超时。ReentrantLock
:是 Java 并发包中更灵活的锁,可以实现公平锁、超时等待、响应中断。ReentrantLock lock = new ReentrantLock(); lock.lock(); try {// 临界区代码 } finally {lock.unlock(); }
ReadWriteLock
:读写锁,读锁共享,写锁独占。ReentrantReadWriteLock
是常用实现。StampedLock
:支持乐观读锁的锁,可以提高读多写少场景下的性能。
三、死锁及其避免
死锁是指两个或多个线程相互等待对方释放资源,导致程序无法继续执行。发生死锁的条件包括:
- 互斥条件:一个资源一次只能被一个线程占用。
- 占有且等待:一个线程在持有资源的同时,仍在请求其他资源。
- 不可剥夺:资源不能被强制释放,只能由持有它的线程释放。
- 环形等待:多个线程形成一个循环等待链。
3.1 死锁示例
以下代码展示了两个线程死锁的情况:
class DeadlockDemo {private final Object lock1 = new Object();private final Object lock2 = new Object();public void method1() {synchronized (lock1) {System.out.println("Thread 1: Holding lock 1...");try { Thread.sleep(10); } catch (InterruptedException e) {}synchronized (lock2) {System.out.println("Thread 1: Holding lock 2...");}}}public void method2() {synchronized (lock2) {System.out.println("Thread 2: Holding lock 2...");try { Thread.sleep(10); } catch (InterruptedException e) {}synchronized (lock1) {System.out.println("Thread 2: Holding lock 1...");}}}
}
这里,method1
和 method2
分别尝试获取 lock1
和 lock2
,导致两个线程相互等待对方释放锁,从而产生死锁。
3.2 避免死锁的方法
- 破坏环形等待条件:规定获取锁的顺序,避免多个线程在请求资源时形成环。
- 使用
tryLock
:在等待一段时间后自动放弃,避免长时间等待锁,ReentrantLock
提供了tryLock()
方法。if (lock.tryLock(1000, TimeUnit.MILLISECONDS)) {try {// 临界区代码} finally {lock.unlock();} }
- 避免嵌套锁:尽量减少锁的嵌套,或者统一加锁顺序。
- 使用超时机制:设置线程获取资源的等待时间,超时后主动释放锁并重试,避免无限期等待。
3.3 死锁检测工具
JVM 提供了 jstack
工具,可以用于分析线程堆栈信息,检查是否发生死锁。
相关文章:
java的无锁编程和锁机制
Java 的并发编程中,为了保证线程安全和高性能,采用了两种主要的同步手段:锁机制和无锁编程。以下是对锁机制、无锁编程、死锁及其避免的详细讲解。 一、无锁编程 无锁编程通过原子操作来避免传统锁,从而减少线程的上下文切换&am…...
vue实现富文本编辑器上传(粘贴)图片 + 文字
vue实现富文本编辑器上传(粘贴)图片 文字 1.安装插件 npm install vue-quill-editor -s2.在使用vue-quill-editor富文本的时候,对于图片的处理经常是将图片转换成base64,再上传数据库,但是base64不好存储。 原理&a…...

子集和全排列(深度优先遍历)问题
欢迎访问杀马特主页:小小杀马特主页呀! 目录 前言: 例题一全排列: 1.题目介绍: 2.思路汇总: 3.代码解答: 例题二子集: 题目叙述: 解法一: 1.思路汇总…...
判断检测框是否在感兴趣区域(ROI)内
判断检测框是否在感兴趣区域(ROI)内 在计算机视觉和图像处理中,我们经常需要确定一个矩形检测框是否位于一个特定的感兴趣区域(Region of Interest, ROI)内。这个ROI可以是一个多边形,而检测框则是一个矩形…...

正点原子阿尔法ARM开发板-IMX6ULL(九)——关于SecureCRT连接板子上的ubuntu
文章目录 一、拨码器二、SecureCRT 一、拨码器 emmm,也是好久没学IMX6ULL了,也是忘了拨码器决定了主板的启动方式 一种是直接从TF卡中读取文件(注意这里是通过imdownload软件编译好了之后,通过指令放入TF卡) 一种是现在这种用串口…...
微信支付Java+uniapp微信小程序
JS: request.post(/vip/pay, {//这是自己写的java支付接口id: this.vipInfo.id,payWay: wechat-mini}).then((res) > {let success (res2) > {//前端的支付成功回调函数this.$refs.popup.close();// 支付成功刷新当前页面setTimeout(() > {this.doGetVipI…...

【NOIP提高组】加分二叉树
【NOIP提高组】加分二叉树 💐The Begin💐点点关注,收藏不迷路💐 设一个n个节点的二叉树tree的中序遍历为(l,2,3,…,n),其中数字1,2,3,…,n为节点编号。每个节点都有一个分数(均为正整…...

HarmonyOS 相对布局(RelativeContainer)
1. HarmonyOS 相对布局(RelativeContainer) 文档中心:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-layout-development-relative-layout-V5 RelativeContainer为采用相对布局的容器,支持容器内部的子元素设…...
webpack5搭建react脚手架详细步骤
1. 初始化项目 首先,创建一个新目录并初始化项目: bash mkdir create-react cd create-react pnpm init --y git init 这里使用pnpm作为包管理工具,因为它在处理依赖和速度上表现更好。 2. 安装React和TypeScript 安装React和React-DOM…...
速盾:高防cdn怎么拦截恶意ip?
高防CDN(Content Delivery Network)是一种用于防御网络攻击和提供高可用性的服务。它通过分发网络流量,将用户的请求导向最近的服务器,从而提高网站的加载速度和稳定性。然而,不可避免地,有些恶意IP地址会试…...

太阳能面板分割系统:训练自动化
太阳能面板分割系统源码&数据集分享 [yolov8-seg-EfficientHead&yolov8-seg-vanillanet等50全套改进创新点发刊_一键训练教程_Web前端展示] 1.研究背景与意义 项目参考ILSVRC ImageNet Large Scale Visual Recognition Challenge 项目来源AAAI Globa…...

C++笔记---位图
1. 位图的概念 位图(Bitmap)是一种基于位操作的数据结构,用于表示一组元素的集合信息。它通常是一个仅包含0和1的数组,每个元素对应一个二进制位,若该元素存在,则对应的位为1;若不存在ÿ…...
ABC370
## A - Raise Both Hands (模拟) 题意:输入l,r,如果l1r0输出yes,l0r1输出no,否则输出Invalid 代码: #include<bits/stdc.h> using namespace std; typedef long long ll; vo…...

C语言[求x的y次方]
C语言——求x的y次方 这段 C 代码的目的是从用户输入获取两个整数 x 和 y ,然后计算 x 的 y 次幂(不过这里有个小错误,实际计算的是 x 的 (y - 1) 次幂,后面会详细说),最后输出结果。 代码如下: #include…...

JavaScript part2
一.前言 前面我们讲了一下js的基础语法,但是这些还是远远不够的,我们要想操作标签,实现一个动态且好看的页面,就得学会BOM和DOM,这些都是浏览器和页面的,这样我们才能实现一个好看的页面 二.BOM对象 BOM…...

HarmonyOS开发 - 本地持久化之实现LocalStorage实例
用户首选项为应用提供Key-Value键值型的数据处理能力,支持应用持久化轻量级数据,并对其修改和查询。数据存储形式为键值对,键的类型为字符串型,值的存储数据类型包括数字型、字符型、布尔型以及这3种类型的数组类型。 说明&#x…...

【C++打怪之路Lv12】-- 模板进阶
#1024程序员节|征文# 🌈 个人主页:白子寰 🔥 分类专栏:重生之我在学Linux,C打怪之路,python从入门到精通,数据结构,C语言,C语言题集👈 希望得到您…...
第23周Java主流框架入门-SpringMVC 2.RESTful开发风格
课程笔记:RESTful 开发风格 课程介绍 本节课程介绍 RESTful 开发风格,以及如何在 Spring MVC 中应用这种开发模式。传统 MVC 开发通过 Servlet、JSP 和 Java Bean 实现前后端交互,而 RESTful 开发提供了一种新的理念,更适合现代…...

QT枚举类型转字符串和使用QDebug<<重载输出私有枚举类型
一 将QT自带的枚举类型转换为QString 需要的头文件: #include <QMetaObject> #include <QMetaEnum> 测试代码 const QMetaObject *metaObject &QImage::staticMetaObject;QMetaEnum metaEnum metaObject->enumerator(metaObject->indexOf…...

手机柔性屏全贴合视觉应用
在高科技日新月异的今天,手机柔性显示屏作为智能手机市场的新宠,以其独特的可弯曲、轻薄及高耐用性特性引领着行业潮流。然而,在利用贴合机加工这些先进显示屏的过程中,仍面临着诸多技术挑战。其中,高精度对位、应力控…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...