Java的锁机制详解
在并发编程中,锁 是用于控制多个线程对共享资源进行访问的工具。Java提供了多种锁机制,从最基础的 synchronized 到高级的 ReentrantLock,这些锁帮助我们确保线程安全,并能有效避免数据竞争和死锁问题。

1. synchronized 关键字
synchronized 是Java中最简单的锁机制。它可以锁住方法或者代码块,确保某个线程在访问共享资源时,其他线程无法访问同一个资源。
示例代码:同步方法
public class SynchronizedExample {public synchronized void synchronizedMethod() {System.out.println("Thread " + Thread.currentThread().getName() + " is executing synchronized method.");}
}
在上述代码中,synchronizedMethod 方法被 synchronized 关键字修饰,意味着同一时间只能有一个线程执行该方法。
示例代码:同步代码块
public class SynchronizedBlockExample {private final Object lock = new Object();public void synchronizedBlock() {synchronized (lock) {System.out.println("Thread " + Thread.currentThread().getName() + " is executing synchronized block.");}}
}
使用同步代码块可以灵活地锁定某个对象(如上例中的 lock),只锁住需要保护的部分,而不是整个方法。
锁的粒度问题
synchronized 锁的粒度较粗,可能会导致性能瓶颈。对于更复杂的并发场景,ReentrantLock 等更灵活的锁机制是更好的选择。
2. ReentrantLock
ReentrantLock 是 Java java.util.concurrent.locks 包中的高级锁,它提供了更丰富的功能,如:公平锁、可重入性、可中断锁 等。
2.1 基本使用
import java.util.concurrent.locks.ReentrantLock;public class ReentrantLockExample {private final ReentrantLock lock = new ReentrantLock();public void execute() {lock.lock(); // 获取锁try {System.out.println("Thread " + Thread.currentThread().getName() + " is executing.");} finally {lock.unlock(); // 释放锁}}
}
在这个例子中,我们显式地调用 lock.lock() 来获取锁,并在 finally 中确保锁会被释放,以防止因异常导致死锁。
2.2 公平锁
默认情况下,ReentrantLock 是非公平锁,即等待时间长的线程不一定优先获得锁。你可以通过构造函数指定是否为公平锁:
ReentrantLock fairLock = new ReentrantLock(true); // 公平锁
公平锁确保先请求锁的线程先获得锁,但相对性能较低。
3. ReadWriteLock
ReadWriteLock 是一种更细粒度的锁,它允许多个读线程同时访问共享资源,但在有写操作时,写线程会独占资源。典型的实现是 ReentrantReadWriteLock。
示例代码
import java.util.concurrent.locks.ReentrantReadWriteLock;public class ReadWriteLockExample {private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();public void read() {rwLock.readLock().lock();try {System.out.println("Thread " + Thread.currentThread().getName() + " is reading.");} finally {rwLock.readLock().unlock();}}public void write() {rwLock.writeLock().lock();try {System.out.println("Thread " + Thread.currentThread().getName() + " is writing.");} finally {rwLock.writeLock().unlock();}}
}
这种锁的优势在于读操作不互斥,当多个线程只读数据时,能够提高系统的吞吐量。但在写操作时,所有的读操作会被阻塞,确保数据的一致性。
4. 锁优化技术
4.1 偏向锁
偏向锁 是Java的轻量级锁优化策略。它假定大多数情况下锁不会被多个线程竞争,因此,第一次获取锁时,锁会偏向获取锁的线程。如果没有其他线程竞争,这个线程之后获取锁的代价几乎为零。
偏向锁适用于线程独占资源的场景,而不适用于高并发的竞争场景。
4.2 自旋锁
自旋锁 是通过让线程循环等待一段时间,而不立即进入阻塞状态,来减少上下文切换的开销。在高并发的环境中,如果线程持有锁的时间非常短,自旋锁可以提高性能。
Java在ReentrantLock的实现中结合了自旋锁的概念,当锁的竞争不激烈时,避免线程进入阻塞状态。
4.3 Lock Support
Java还提供了 LockSupport 类,用于线程的挂起和唤醒。这是实现高级并发工具(如CountDownLatch、CyclicBarrier等)的基础。
5. 总结
- synchronized:简单易用,适合基本的锁定需求,但灵活性较差。
- ReentrantLock:提供更丰富的功能,如可重入、锁超时、公平锁等,适用于复杂的并发场景。
- ReadWriteLock:读写分离,提高读多写少场景下的并发性能。
- 锁优化:如偏向锁、自旋锁、Lock Support等技术提高了锁的性能,适用于特定场景。
Java的锁机制虽然功能强大,但在实际开发中,我们需要根据具体场景选择合适的锁,并合理使用,以避免锁的滥用带来的性能问题。
相关文章:
Java的锁机制详解
在并发编程中,锁 是用于控制多个线程对共享资源进行访问的工具。Java提供了多种锁机制,从最基础的 synchronized 到高级的 ReentrantLock,这些锁帮助我们确保线程安全,并能有效避免数据竞争和死锁问题。 1. synchronized 关键字…...
用户登录与信息管理:实现小程序登录与用户信息存储
用户登录与信息管理:实现小程序登录与用户信息存储 在现代的移动应用中,用户登录与信息管理是构建个性化用户体验的基础。小程序作为轻量级的应用形式,在简化开发流程的同时,也需要我们妥善管理用户的登录状态与用户信息。本文将…...
Java如何调用构造函数和方法以及使用
调用构造函数的格式 构造函数在创建新对象时被调用。调用格式如下: ClassName objectName new ClassName(parameters); ClassName:你需要创建其实例的类的名称。 objectName:你将创建的对象的名称。 parameters:如果你使用的是…...
TFBoys谁最重
题目 使用go语言设计一个程序计算TFBoys谁最重,要求使用结构体表示TFBoys三个成员,设计函数计算三个重量的最大值。 程序 package main import ("fmt") type Person struct {Name stringWeight float64} func (p Person) GetWeigh…...
scp 通过中间机器进行远程拷贝
有时候,我们想要通过 scp将一台机器上的文件拷贝至另外一台机器,但这两台机器可能没有直接联通,需要通过中间机器进行跳转才能访问,一个麻烦的办法就是,先将文件拷贝至中间机器,然后再从中间机器拷贝至另外…...
探索 Python 高精度计算的奥秘:mpmath 库全解析
文章目录 探索 Python 高精度计算的奥秘:mpmath 库全解析背景:为何选择 mpmath?第二部分:mpmath 是什么?第三部分:如何安装 mpmath?第四部分:mpmath 函数使用示例第五部分࿱…...
<<迷雾>> 第10章 用机器做一连串的加法(1)--使用两排开关分别给出被加数和加数 示例电路
info::操作说明 鼠标单击逻辑输入切换 0|1 状态 primary::在线交互操作链接 https://cc.xiaogd.net/?startCircuitLinkhttps://book.xiaogd.net/cyjsjdmw-examples/assets/circuit/cyjsjdmw-ch10-01-5-bit-adder.txt 原图...
Stable Diffusion最新版nowebui的api使用详解
最近在使用stable diffusion最新版的Stable Diffusion WebUI Forge进行api调用,下面来一步一步的进行展开吧!!! 1、下载lllyasviel/stable-diffusion-webui-forge GitHub - lllyasviel/stable-diffusion-webui-forgeContribute to lllyasviel/stable-diffusion-webui-for…...
云服务器架构详解:X86计算_ARM_GPU/FPGA/ASIC_裸金属_超级计算集群
阿里云服务器架构有什么区别?X86计算、ARM计算、GPU/FPGA/ASIC、弹性裸金属服务器、超级计算集群有什么区别?阿里云服务器网aliyunfuwuqi.com分享云服务器ECS架构详细说明: 阿里云服务器ECS架构说明 阿里云服务器ECS架构 X86计算 X86计算架…...
高级java每日一道面试题-2024年10月4日-数据库篇-MySQL索引底层结构为什么使用B+树?
如果有遗漏,评论区告诉我进行补充 面试官: MySQL索引底层结构为什么使用B树? 我回答: 该面试题本质还是在考察B树的数据结构和在数据库系统中的应用,下边是详细的回答。 B树的基本特性 B 树的结构特点 非叶子节点只存储键值信息,不存储…...
【JVM】内存分析工具JConsole/Visual VM
1 缘起 日常补充JVM调优,调优实践前需要学习一些理论做支撑, JVM调优三步:理论>GC分析>JVM调优, 我们会有一些玩笑话说,做了这么久Java开发,做过JVM调优吗? 做过,面试时。当然…...
一静 、二平 、三忍 、四让、五淡
一静 、二平 、三忍 、四让、五淡。 作者:儒风君 来源:儒风大家(ID: rufengdajia) 古人为人、处事、修身,都有独特的章法。 一静、二平、三忍、四让、五淡。 说透中国人的大智慧。 1 静 《道德经》里讲:“清静为天下正。”…...
js 深入理解函数(一):函数的本质
目录 概述1. 箭头函数2. 函数名 :指向函数的指针3. 理解参数3.1 arguments 对象的作用3.2 arguments 的注意点3.3 箭头函数中的参数 4. 没有重载5. 默认参数值5.1 ES 6 支持显示定义默认参数5.2 传 undefined 等于没有传值5.3 arguments 不反映参数默认值5.4 默认值…...
MySql表结构设计
创建 create table 表名(字段1 字段类型 [约束] [comment 字段1注释],...) [comment 表注释];约束是作用于表中字段上的规则,用于限制存储在表中的数据。它的目的是保证数据库中数据的正确性、有效性和完整性。 约束描述关键字非空约束限制该字段不能为nullnot nu…...
java:pdfbox 3.0 去除扫描版PDF中文本水印
官网下载 https://pdfbox.apache.org/download.html下载 pdfbox-app-3.0.3.jar cd D:\pdfbox 运行 java -jar pdfbox-app-3.0.3.jar java -jar pdfbox-app-3.0.3.jar Usage: pdfbox [COMMAND] [OPTIONS] Commands:debug Analyzes and inspects the internal structu…...
python知识点100篇系列(17)-替换requests的python库httpx
Requests 是使用 Apache2 Licensed 许可证的 基于Python开发的HTTP 库,其在Python内置模块的基础上进行了高度的封装,使用Requests可以轻而易举的完成浏览器可有的任何操作。 但是在python3.6之后,出现了一个requests的替代选项; httpx httpx是Python新一代的网络请求库…...
python 实现graph list图列算法
graph list图列算法介绍 图列(Graph List)算法通常指的是在图的表示中,使用列表(List)或更具体地说,邻接表(Adjacency List)来表示图的一种算法。邻接表是图的一种常见表示方法&…...
LFU算法 初始频率 动态频率
LFU(Least Frequently Used)算法是一种缓存淘汰策略,其核心思想是根据数据的访问频率来决定淘汰哪些数据。具体来说, LFU算法认为如果一个数据在过去一段时间内被访问的次数很少,那么它在未来被再次访问的概率也…...
Spring Boot 进阶-详解SpringBoot的复杂数据校验规则
在之前的文章中,我们介绍了SpringBoot整合JSR-303规则来完成数据校验操作。接下来我们来聊一聊关于数据校验的具体用法。 之前的文章中举过一个简单的例子通过学生信息提交的例子来介绍了关于数据校验如何去做。那么接下来这篇文章,我们就来看看对于一些复杂的数据校验如何完…...
wsl环境下安装Ubuntu,并下载MySQL5.7
安装操作需root权限,切换root用户有两种方式: 1-通过 sudo su - ,切换到root用户(登录后长期有效)。 2-在每一个命令前加上sudo,临时提升权限(仅对一条命令有效)。 1、下载apt仓库…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
