Java 中的各种锁

news2025/1/2 22:54:04

​ Java 中我们经常听到各种锁,例如悲观锁,乐观锁,自旋锁等等。今天我们将 Java 中的所有锁放到一起比较一下,并分析各自锁的特点,让大家能够快捷的理解相关知识。

1、悲观锁 VS 乐观锁

从概念上来说

悲观锁:

​ 在对同一个数据并发操作的时候,认为使用到的数据一定被别的线程修改数据,因此获取数据的时候先加锁,保证数据不会被别的线程修改。例如: 常用的 synchronized 关键字和 Lock 的实现类的使用都是悲观锁

乐观锁:

​ 同悲观锁相反,认为使用到的数据不会有别的线程修改数据,所以不会添加锁,只有在更新数据的时候去判断之前有没有别的线程更新了这个数据。如果没有被更新,则将修改数据写入,如果数据被其他线程修改,则报错或者重试。通常是使用 CAS 算法操作。

从上面的概念来说

悲观锁适合写操作多的场景: 先加锁可以保证写操作时数据正确

乐观锁适合读操作多的场景: 不加锁的特点能够使其读操作的性能大幅提高。

代码实例:

悲观锁的调用方式

//synchronized使用方式
public synchronized void testMethod() {
	// 操作同步业务
}

// ReentrantLock
private ReentrantLock lock = new ReentrantLock();

public void modifyPublicResources() {
	lock.lock();
	// 操作同步业务
	lock.unlock();
}

乐观锁的调用方式

private AtomicInteger atomicInteger = new AtomicInteger(); 
atomicInteger.incrementAndGet(); //执行自增,底层是 CAS 算法。

总结:

其实悲观锁和乐观锁的区别在于是否锁住同步资源. 如果锁住同步资源就是悲观锁,不锁住同步资源就是乐观锁。

2、自旋锁 VS 适应性自旋锁

Java 线程状态切换是需要操作系统操作 CPU 状态完成的。也就是需要从用户态切换到内核态。在很多场景下,同步资源的锁定还是非常短,为了这一段时间去调用内核去切换进行状态,就会得不偿失。因此优化这种情况,我们不如让线程‘等一等’。例如自旋一下,当同步资源立即的时候,能够立即操作,提升速度。

请添加图片描述
请添加图片描述

从上面两张图,我们可以看下自旋锁和非自旋锁的区别。

自旋锁本身也是有缺点的,它不能代替阻塞。短暂自旋等待可以提高同步资源的加锁速度。但是长时间的自旋,就会白白浪费 CPU, 因此一般我们会尝试设置自旋次数,如果超过这个次数之后,就应该挂起线程。

可以通过-XX:PreBlockSpin参数来设置一个大致的自旋次数范围。

在实际应用中,一般不建议手动设置这个参数,因为自适应自旋锁通常能够做出更合理的决策。

讲完自旋锁,那我们看下自适应自旋锁。

所谓的自适应自旋锁就是自旋次数不是固定的。而是由前一次在同一个锁上的自旋时间以及锁的拥有者的状态来决定。如果在同一个锁对象上,自旋等待刚刚成功获取过锁。并且持锁的线程并在运行,那么虚拟机就会认为这次自旋很有可能再次成功,进而允许自旋等待持续相对更长的时间。例如前一次是 10次循环,这次可能是 20 次循环

总结:

其实所谓的自旋锁就是在加锁同步资源失败的时候,线程不阻塞的情况。

3、无锁 VS 偏向锁 VS 轻量级锁 VS 重量级锁

img

以上是 synchronized 锁膨胀的过程,其中涉及到无锁,轻量级锁,重量级锁的转变过程。这里我们先大致了解一下。synchronized 锁膨胀的详细过程 后续详细分析。

总结:

​ 偏向锁通过对比Mark Word解决加锁问题,避免执行CAS操作。而轻量级锁是通过用CAS操作和自旋来解决加锁问题,避免线程阻塞和唤醒而影响性能。重量级锁是将除了拥有锁的线程以外的线程都阻塞

4、公平锁 VS 非公平锁

请添加图片描述

上图是 AQS 的整体原理图。所谓的公平和非公平就是如果获取不到同步资源的时候,进入队列的方式是否公平。

在 java 1.8 中 ReentrantLock的实现方式 分为公平锁和非公平锁两种实现方式。其中主要区别就是在进入队列的时候,是否尝试去加锁。

公平锁: 如果获取不到同步资源就是乖乖的进入阻塞队列

非公平锁: 如果获取不到同步资源,在进入队列之前,再次去尝试加锁。如果加锁失败才会进去到队列中。

非公平锁比较常用

因为非公平锁的效率较高。同步加锁的时候比较短,在进队列之前再重新加锁的时候,有可能获加锁成功。并且线程不会进入到内核态,并阻塞唤醒。

5、可重入锁和非可重入锁

public class Reentrant {

    public synchronized void method1() {
        System.out.println("method1");
        method2();
    }

    public synchronized void method2() {
        System.out.println("method2");
    }
}

我们看下上面的代码。当一个线程调用 method1()的时候,需要加锁成功。当调用 method2()的时候,也需要加锁成功才能执行。如果synchronized 内置锁是不可重入的。那就会导致无法调用 method2()。因为调用 method1()的加锁成功,但是锁未释放。就会导致调用 method2()方法 无法加锁成功。造成死锁问题。

synchronized 和 ReentrantLock 都是比较常见的重入锁。

总结:

​ 如果一个线程在多个流程中能获取到同一把锁,就是可重入锁。如果不能,则是非可重入锁。

6、独享锁和共享锁

独享锁,是指该锁一次只能被一个线程所持有。如果线程A对数据x加上排它锁后,则其他线程不能再对x加任何类型的锁。获得排它锁的线程即能读数据又能修改数据。

共享锁 是指该锁可被多个线程所持有。如果线程A对数据x加上共享锁后,则其他线程只能对x再加共享锁,不能加排它锁。获得共享锁的线程只能读数据,不能修改数据。

总结:

多个线程能不能共享一把锁?如果能,就是共享锁,如果不能 就是排他锁。

以上就是 Java 中的各种锁。部分锁的内容讲的比较概括,后续会有文章详细地讲解。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【开源免费】基于SpringBoot+Vue.JS租房管理系统(JAVA毕业设计)

本文项目编号 T 102 ,文末自助获取源码 \color{red}{T102,文末自助获取源码} T102,文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

报考重庆大学计算机研究生有哪些要求?

想要报考重庆大学计算机研究生,首要你要确定考专硕还是学硕,考什么内容,需要买什么书?以及考研期间一些信息获取渠道等。下面C哥将对以上问题进行详细解答。 1.报考条件: 报考重大计算机研究生与重大其他大多数专业条…

爬虫与反爬虫实现全流程

我选取的网页爬取的是ppt nba版 需要的工具:pycharm,浏览器 爬虫需要观察它的网页信息,然后开始首先爬取它的html,可以看到有人气,标题,日期,咨询 可以看到用get方法 import requests url"https://img-home.csdnimg.cn/images/20230724024159.png?origin_urlhttps%3A%2…

Llama 3 后训练(三)

目录 4. 后训练 4.1 建模 图表解读 4.1.1 聊天对话格式 4.1.2 奖励建模 4.1.3 监督微调(Supervised Finetuning) 4.1.4 直接偏好优化(Direct Preference Optimization) 4.1.5 模型平均(Model Averaging&#x…

小程序配置文件 —— 15 页面配置

页面配置 小程序的页面配置,也称为局部配置,每一个小程序页面也可以使用自己的 .json 文件来对页面的窗口表现进行配置; 需要注意的是:页面配置文件的属性和全局配置文件中的 window 属性几乎一致,只不过这里不需要额…

【设计与实现】基于Bootstrap的地方旅游管理系统的设计与实现

目录 第一章 绪论 1.1 研究现状 1.2 设计原则 1.3 研究内容 第四章 系统设计 4.1系统结构设计 4.2系统顺序图设计 4.3数据库设计 第五章 系统实现 5.1登录模块的实现 第一章 绪论 1.1 研究现状 时代的发展,我们迎来了数字化信息时代,它正在渐…

如何使用React,透传各类组件能力/属性?

在23年的时候,我主要使用的框架还是Vue,当时写了一篇“如何二次封装一个Vue3组件库?”的文章,里面涉及了一些如何使用Vue透传组件能力的方法。在我24年接触React之后,我发现这种扩展组件能力的方式有一个专门的术语&am…

使用Excel制作通达信自定义“序列数据“

序列数据的视频教程演示 Excel制作通达信自定义序列数据 1.序列数据的制作方法:删掉没有用的数据(行与列)和股代码格式处理,是和外部数据的制作方法是相同,自己上面看历史博文。只需要判断一下,股代码跟随的…

VuePress搭建个人博客

VuePress搭建个人博客 官网地址: https://v2.vuepress.vuejs.org/zh/ 相关链接: https://theme-hope.vuejs.press/zh/get-started/ 快速上手 pnpm create vuepress vuepress-starter# 选择简体中文、pnpm等, 具体如下 .../19347d7670a-1fd8 | 69 .../19…

《机器学习》从入门到实战——线性回归

目录 一、什么是线性回归 二、一元线性回归模型 三、多元线性回归模型 四、误差项分析 1、误差项是否可以忽略 2、误差项的特点 3、误差项满足高斯分布(正太分布) (1)、高斯分布公式 (2)、公式推导 …

Java - 日志体系_Apache Commons Logging(JCL)日志接口库_适配Log4j2 及 源码分析

文章目录 PreApache CommonsApache Commons ProperLogging (Apache Commons Logging ) JCL 集成Log4j2添加 Maven 依赖配置 Log4j2验证集成 源码分析1. Log4j-jcl 的背景2. log4j-jcl 的工作原理2.1 替换默认的 LogFactoryImpl2.2 LogFactoryImpl 的实现…

brupsuite的基础用法常用模块(1)

proxy模块: Options: 设置代理端口,默认为8080端口,若8080端口被占用可在该界面更改代理端口. HTTP history: 拦截的历史请求,右键可做更多操作,很多操作与其他模块有关。(清除历史的话右键选择clear p…

概率统计与随机过程--作业7

编程题 分别使用混合高斯聚类算法(GMM)和K-Means聚类算法将agricultural_economy.xlsx文件中的9个样本聚成2类(可以使用sklearn的GaussianMixture和KMeans),用不同颜色绘图显示各类样本点,并与“最短距离聚…

【Unity3D】ECS入门学习(十二)IJob、IJobFor、IJobParallelFor

IJob&#xff1a;开启单个线程进行计算&#xff0c;线程内不允许对同一个数据进行操作&#xff0c;也就是如果你想用多个IJob分别计算&#xff0c;将其结果存储到同一个NativeArray<int>数组是不允许的&#xff0c;所以不要这样做&#xff0c;如下例子就是反面教材&#…

MicroDiffusion——采用新的掩码方法和改进的 Transformer 架构,实现了低预算的扩散模型

介绍 论文地址&#xff1a;https://arxiv.org/abs/2407.15811 现代图像生成模型擅长创建自然、高质量的内容&#xff0c;每年生成的图像超过十亿幅。然而&#xff0c;从头开始训练这些模型极其昂贵和耗时。文本到图像&#xff08;T2I&#xff09;扩散模型降低了部分计算成本&a…

Java - 日志体系_Simple Logging Facade for Java (SLF4J)日志门面_SLF4J集成Log4j1.x 及 原理分析

文章目录 Pre官网集成Log4j1.x步骤POM依赖使用第一步&#xff1a;编写 Log4j 配置文件第二步&#xff1a;代码 原理分析1. 获取对应的 ILoggerFactory2. 根据 ILoggerFactory 获取 Logger 实例3. 日志记录过程 小结 Pre Java - 日志体系_Apache Commons Logging&#xff08;JC…

详解VHDL如何编写Testbench

1.概述 仿真测试平台文件(Testbench)是可以用来验证所设计的硬件模型正确性的 VHDL模型&#xff0c;它为所测试的元件提供了激励信号&#xff0c;可以以波形的方式显示仿真结果或把测试结果存储到文件中。这里所说的激励信号可以直接集成在测试平台文件中&#xff0c;也可以从…

Linux day 11 28

一.Linux简介 1.1 Linux介绍 Linux 是一套免费使用和自由传播的操作系统。说到操作系 统&#xff0c;大家比较熟知的应该就是 Windows 和 MacOS 操作系统&#xff0c; 我们今天所学习的 Linux 也是一款操作系统。 1.2 Linux发展历史 时间&#xff1a; 1991 年 地点&#xf…

【深度学习环境】NVIDIA Driver、Cuda和Pytorch(centos9机器,要用到显示器)

文章目录 一 、Anaconda install二、 NIVIDIA driver install三、 Cuda install四、Pytorch install 一 、Anaconda install Step 1 Go to the official website: https://www.anaconda.com/download Input your email and submit. Step 2 Select your version, and click i…

Lecture 17

10’s Complement Representation 主要内容&#xff1a; 1. 10’s 补码表示: • 10’s 补码表示法需要指定表示的数字位数&#xff08;用 n 表示&#xff09;。 • 表示的数字取决于 n 的位数&#xff0c;这会影响具体数值的解释。 2. 举例: • 如果采用 3 位补码&…