JavaEE之锁策略,cas 和 synchronized 优化过程深入浅出

目录

题外话

正题

 锁策略

乐观锁和悲观锁

轻量锁和重量锁

CAS算法(Compare And Swap)

自旋锁和挂起等待锁

普通互斥锁和读写锁

公平锁和非公平锁

可重入锁和不可重入锁

synchronized原理

基本特点

锁升级

其它锁优化

锁消除

锁粗化

小结


 

题外话

时间紧任务重,直接开始讲解,今天内容大都是概念内容

正题

 锁策略

乐观锁和悲观锁

乐观锁:乐观锁会认为锁竞争不是很激烈,做的准备工作比较少,开销更小(时间开销,系统资源开销),效率更高一些

悲观锁:悲观锁会认为锁竞争很激烈,做的准备工作比较多,开销更大(时间开销,系统资源开销),效率更低一些

具体使用哪种锁要看实际情况,应用场景

乐观锁一般用在线程竞争一个锁冲突比较少的情况

悲观锁恰恰相反,一般用在线程竞争一个锁冲突比较多的情况

轻量锁和重量锁

轻量锁:开销比较小的锁,需要在用户态中完成,加锁机制一般依赖CAS算法实现

重量锁:开销比较大的锁,需要在内核态中完成, 加锁机制重度依赖了OS提供了mutex

CAS算法(Compare And Swap)

CAS算法是一种无锁算法

无锁算法:基于硬件原语实现,在不使用锁(没有线程被阻塞)的情况下实现多线程之间的变量同步

算法涉及到三个操作数:

需要读写的内存值V

进行比较的值A

要写入的新值B

返回值为boolean类型

算法执行步骤

A和V先比较是否相等(比较)

如果相等,把B写入V(交换)

相等返回true,不相等返回false

自旋锁和挂起等待锁

自旋锁:当线程获取不到锁的时候,不会放弃CPU,会频繁的循环尝试去获取锁,会造成CPU的资源浪费,当锁释放的时候,可以第一时间获取锁, synchronized中的轻量级锁策略⼤概率就是通过⾃旋锁的方式实现的.

挂起等待锁:当线程获取不到锁的时候,会进行堵塞等待,放弃CPU,进入等待队列中,等到锁释放的时候再让系统调度

举个例子

先说自旋锁

挂起等待锁

希望以上例子能帮助大家更好的理解,自旋锁和挂起等待锁

普通互斥锁和读写锁

普通互斥锁:在Java中,只有加锁和解锁两个操作的锁,就是普通互斥锁,如synchronized

读写锁:多线程之间,数据的读取⽅之间不会产⽣线程安全问题,但数据的写入方互相之间以及和读者之间都 需要进行互斥。如果两种场景下都⽤同⼀个锁,就会产⽣极⼤的性能损耗。所以读写锁因此⽽产⽣。

读锁和读锁之间不会产生互斥

            写锁和写锁之间会产生互斥

            写锁和读锁之间会产生互斥

synchronized不是读写锁

公平锁和非公平锁

公平锁:当多个线程获取锁的时候,会根据先来后到的原则,当锁被释放的时候,最先等待的线程会获取到锁,公平锁需要记录线程先来后到,需要额外的数据结构

非公平锁:当多个线程获取锁的时候,不会根据先来后到的原则,而是根据机会均等的原则,当锁被释放的时候,每个线程都有机会获取到锁

synchronized是非公平锁

举个例子:当厕所里有人占用,有很多人排队,而你比其他人来的都早,等厕所里面的人出来,你就可以占用厕所,这就是公平锁

                当厕所里有人占用,但是这个厕所不能排队,一群人在门口等待,每个人占用厕所的几率是均等的,哪怕你来的很早,也不一定能轮到你

          

可重入锁和不可重入锁

可重入锁:允许一个线程多次获取同一把锁

⽐如⼀个递归函数⾥有加锁操作,递归过程中这个锁会阻塞自己吗?如果不会,那么这个锁就是可重入锁(因为这个原因可重⼊锁也叫做递归锁)。

不可重入锁:不允许一个线程多次获取同一把锁

Java⾥只要以Reentrant开头命名的锁都是可重⼊锁,⽽且JDK提供的所有现成的Lock实现类,包括 synchronized关键字锁都是可重⼊的。

synchronized原理

基本特点

结合上⾯的锁策略,我们就可以总结出,synchronized具有以下特性(只考虑JDK1.8):

1. 开始时是乐观锁,如果锁冲突频繁,就转换为悲观锁.

2. 开始是轻量级锁实现,如果锁被持有的时间较⻓,就转换成重量级锁.

3. 实现轻量级锁的时候⼤概率⽤到的⾃旋锁策略

4. 是⼀种不公平锁

5. 是⼀种可重⼊锁

6. 不是读写锁

锁升级

JVM将synchronized锁分为⽆锁、偏向锁、轻量级锁、重量级锁状态。会根据情况,进⾏依次升 级。

无锁:代码中没有加锁

偏向锁:第一个尝试加锁的进程,会进入"偏向锁"的状态,偏向锁不是真的加锁,而是给对象头中做⼀个"偏向锁的标记"

偏向锁本质上相当于"延迟加锁".能不加锁就不加锁,尽量来避免不必要的加锁开销. 但是该做的标记还是得做的,否则⽆法区分何时需要真正加锁.

轻量级锁:随着其他线程进入竞争,偏向锁状态被消除,进入轻量级锁状态(自适应的自旋锁).


此处的轻量级锁就是通过CAS来实现.
●通过CAS检查并更新一块内存(比如null =>该线程引用)
如果更新成功,则认为加锁成功
●如果更新失败, 则认为锁被占用,继续自旋式的等待(并不放弃CPU).


自旋操作是一直让CPU空转,比较浪费CPU资源.
因此此处的自旋不会一直持续进行, 而是达到一定的时间/重 试次数,就不再自旋了.
也就是所谓的"自适应"

重量级锁:如果竞争进一步激烈,自旋不能快速获取到锁状态,就会膨胀为重量级锁
此处的重量级锁就是指用到内核提供的mutex.


●执行加锁操作,先进入内核态.在内核态判定当前锁是否已经被占用
●如果该锁没有占用,则加锁成功,并切换回用户态.
●如果该锁被占用,则加锁失败.此时线程进入锁的等待队列,挂起.等待被操作系统唤醒.
●经历了一系列的沧海桑田,这个锁被其他线程释放了,操作系统也想起了这个挂起的线程,于是唤醒这个线程,尝试重新获取锁.

其它锁优化

锁消除

编译器+JVM判断锁是否可消除.如果可以,就直接消除

什么是"锁消除"有些应用程序的代码中,用到了synchronized,但其实没有在多线程环境下.
在单线程情况下,加锁没有必要,而且会浪费资源开销

锁粗化

⼀段逻辑中如果出现多次加锁解锁,编译器+JVM会自动进行锁的粗化

锁粗化就是多个连续加锁,解锁的操作放在一起,这样会使锁的粒度越粗,否则锁的粒度就越细


 

小结

 以上就是本篇博客所有内容

喜欢的麻烦给个三连(点赞关注收藏!!!)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++-基础

C语言介绍 C 是一种通用编程语言,具有高性能、灵活性和广泛的应用领域。它是在 1979 年由 Bjarne Stroustrup 开发的,最初被称为“C with Classes”,随后在 1983 年正式更名为 C。C 基于 C 语言,同时引入了面向对象编程&#xff0…

【MATLAB源码-第51期】基于matlab的粒子群算法(PSO)的栅格地图路径规划。

操作环境: MATLAB 2022a 1、算法描述 粒子群算法(Particle Swarm Optimization,简称PSO)是一种模拟鸟群觅食行为的启发式优化方法。以下是其详细描述: 基本思想: 鸟群在寻找食物时,每只鸟都…

003 【笔记神器】Obsidian:打造属于自己的万能工作台

前言:Obsidian 是一款很多大神都在用的笔记软件,具有强大的功能,能够满足日常各种笔记的需求。强大之处在于:Obsidian 能够安装各种强大的插件,实现各种功能。 废话不多说,玩转 Obsidian 仅需这篇文章足矣&…

Linux/Iclean

Iclean Enumeration nmap 先使用默认规则扫描常用的端口,发现对外开放了 22 和 80 端口,然后扫描这两个端口的详细信息,结果如下,很常规的结果,没发现什么有趣的东西 ┌──(kali㉿kali)-[~/vegetable/HTB/Iclean] …

2024年文化、历史与人文艺术与社会发展国际会议(CHHASD2024)

2024年文化、历史与人文艺术与社会发展国际会议(CHHASD2024) 会议简介 2024年国际文化、历史、人文、艺术与社会发展会议(CHHASD2024)将在中国武汉举行,主题为“文化、历史,人文、艺术和社会发展”。CHHASD2024汇集了来自世界各…

反爬虫之代理IP封禁-协采云IP池

反爬虫之代理IP封禁-协采云IP池 1、目标网址2、IP封禁4033、协采云IP池 1、目标网址 aHR0cDovL3d3dy5jY2dwLXRpYW5qaW4uZ292LmNuLw 2、IP封禁403 这个网站对IP的要求很高,短时间请求十几次就会遭关进小黑屋。如下图: 明显是网站进行了反爬处理&…

ubuntu22安装snipaste

Ubuntu 22.04 一、Snipaste 介绍和下载 Snipaste 官网下载链接: Snipaste Downloads 二、安装并使用 Snipaste # 1、进入Snipaste-2.8.9-Beta-x86_64.AppImage 目录(根据自己下载目录) cd /home/jack/Downloads/softwares/AppImage# 2、Snipaste-2.8.9-…

图像分类——综合车辆数据集

一、重要性及意义 智能交通管理:车辆图像分类是智能交通系统(ITS)中的关键组成部分。通过对监控摄像头捕捉到的车辆图像进行自动分类,系统能够实时识别车辆类型、颜色、品牌等信息,进而实现交通流量监控、违章行为检测…

在线知识库如何从零开始搭建?这篇文章来教你!

引言: 有没有想过把那些零散在脑海中的点点滴滴整理起来,建立一个属于自己的在线知识库?无论是个人学习,团队协作,还是企业管理,一个良好的知识库都能帮我们更高效地存储和分享知识。如果你还在为“怎么建知…

YesPMP众包平台 | 活动有礼,现金奖励点击领取!

YesPMP众包平台在线发福利啦,4月16日活动火热开启,现金奖励等你来领,最高可领千元,赶快参与将奖励收入囊中,一起来了解活动细节吧! 一、活动内容: 活动一:【项目征集令】活动&…

告别传统开发,用这11个网站模板搭建的零售线上商城,制作成本都大幅降低了

随着人工智能时代的到来,很多复杂的工作再日益变得简单。比如20年前开发一个在线商城完成支付交易,那是一个不得了的事情,现在的零售巨头淘宝和京东就是在那个时代崛起的。新时代涌现出了许多新的工具,比如使用低代码平台搭建的自…

【网站项目】驾校报名小程序

🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板&#xff…

使用Python生成二维码

1、背景 上一次我们介绍了什么是二维码,读过这篇文章以后,相信大家对二维码已经有了一定的认识,那么有没有想过如何自己动手生成二维码呢?二维码在我们的生活与工作中,都能够做什么呢?今天我们来探讨一下用…

2.Mysql 多实例的部署和应用

Mysql多实例的概念: MySql多实例就是在一台机器上开启多个不同的服务端口,运行多个MySql服务进程,通过不同的socket监听不同的服务端口来提供各自的服务。 这些Mysql多实例共用一套MySql安装程序,使用不同的my.cnf(也可…

ThreadX在STM32上的移植:通用启动文件tx_initialize_low_level.s

在嵌入式系统开发中,实时操作系统(RTOS)的选择对于系统性能和稳定性至关重要。ThreadX是一种广泛使用的RTOS,它以其小巧、快速和可靠而闻名。在本文中,我们将探讨如何将ThreadX移植到STM32微控制器上,特别是…

计算机网络 Cisco路由信息协议(RIP)实验

一、实验内容 1、命名 2、关闭域名解释 3、设置路由器接口IP地址 4、根据要求配置RIP以实现所有客户机都能相互通信 5、配置默认路由 二、实验数据处理 1、建立拓扑图 2、PC机地址配置 主机IP地址子网掩码网关PC110.23.1.2255.255.255.010.23.1.1PC210.23.1.3255.255.2…

[论文分享] Large Language Model guided Protocol Fuzzing

笔记目录 Large Language Model guided Protocol Fuzzing [NDSS 2024]IntroductionConstructionContribution BackgroundProtocol FuzzingChallenges Large Language ModelsMotivation Case StudyLifting Message Grammars: Quality and DiversityEnriching the Seed Corpus: D…

如何利用open3D来生成OCC

config.yaml depth: 10:#深度,设定为10,常用于决定处理或计算的层次或深入程度。 min_density: 0.1:#最小密度,设置为0.1,用于过滤或选择的密度阈值。 n_threads: -1:#线程数,设为-…

群晖(Synology)NAS 启用 SSH

群晖(Synology)NAS 是可以启用 SSH 的。 如果使用 SSH 命令,我们可以在 NAS 上运行相关的 Linux 命令,比如说在服务器网络传输数据上,就会有明显的优势了。 如何启用 进入 NAS 的服务器控制台,然后找到终…

LeetCode 349. 两个数组的交集

LeetCode 349. 两个数组的交集 1、题目 力扣题目链接:349. 两个数组的交集 给定两个数组 nums1 和 nums2 ,返回 它们的 交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 示例 1: 输入:nums1 […