【JavaEE】锁的策略

作者主页:paper jie_博客

本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。

本文于《JavaEE》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造,将MySQL基础知识一网打尽,希望可以帮到读者们哦。

其他专栏:《MySQL》《C语言》《javaSE》《数据结构》等

内容分享:本期将会分享锁的策略知识.这也是面试题常考的问题.

目录

乐观锁与悲观锁

轻量级锁与重量级锁

自旋锁与挂起等待锁

普通互斥锁和读写锁

为什么要引入读写锁

公平锁与非公平锁

可重入锁和不可重入锁

synchronized锁与操作系统自带锁对比

synchronized的优化策略

锁的升级

偏向锁阶段(没有其他锁来竞争)

轻量级锁阶段(有锁竞争,但是不多)

重量级锁阶段(有锁竞争,且很多)

锁消除

锁粗化

相关面试题

你是什么理解乐观锁和悲观锁的,具体怎么实现?

介绍一下读写锁

synchronized是可重入锁吗

什么是自旋锁,为什么要使用自旋锁呢,缺点是什么?


乐观锁与悲观锁

乐观锁就是在加锁前,预估发生锁冲突的概率不大,在进行加锁的时候做的工作不多.这样加锁的速度就会比较快,但是会更容易消耗CPU资源.

悲观锁就是在加锁前,预估发生锁冲突的概率比较大.在进行加锁的时候做的工作就比较多.这样的加锁速度就会比较慢,但这个过程发生问题的几率就不大,还可以更节省CPU资源.

举个栗子:

这就好比两个同学去问问题.A同学认为老师有时间就直接跑过去了,而B同学会先给老师打个电话确认一下老师有没有空再去.A同学就是乐观锁,B同学就是悲观锁. 显而易见,A同学就容易遇到老师很忙的情况,而B同学就可以避免.但老师要是不忙,A同学的速度就会更快.

轻量级锁与重量级锁

轻量级锁就是加锁的开销小,加锁速度快.因为轻量级锁不怎么到涉及线程的调度,所以开销就比较小.

而重量级锁就是加锁的开销比较大,加锁速度慢.因为重量级锁涉及到大量的线程调度,遇到锁竞争就需要将线程调度出CPU,等待解锁再由系统随机唤醒一个等待线程,所所以开销会比较慢.

这里可以理解为轻量级锁就是乐观锁,重量级锁就是悲观锁.而前者是站在结果发生后的角度来评价,后者是站在发生前的角度来预估.

自旋锁与挂起等待锁

自旋锁是轻量级锁的经典实现,自旋锁也就是乐观锁. 它就是在加锁的时候搭配一个while循环,加锁成功就退出循环,要是没有成功发生堵塞,也不会退出CPU,而是通过while循环不断尝试获取到锁. 这种循环就叫做自旋.一旦当其他线程释放锁后,它就可以第一时间拿到锁了. 但是自旋锁只能在锁竞争不大的情况下使用,不然就会白白自旋,浪费CPU资源.

挂起等待锁是重量级锁的经典实现.挂起等待锁也就是悲观锁. 它就是在尝试加锁失败后不会再次尝试获取锁.而是调度出CPU,等待其他线程释放锁后,由系统来随机唤醒一个等待的线程.因为它在等待的过程中会有内核调度器介入,会有大量的线程调度,获取锁的时间就会比较慢.挂起等待锁的适用场景是在锁冲突比较严重的情况下.

而在我们Java中,Synchronized这个锁是一个乐观锁/悲观锁自适应,轻量级锁/重量级锁自适应,自旋/挂起等待锁自适应.它可以根据不同的场景来做切换.

普通互斥锁和读写锁

我们Java的synchronized就是普通互斥锁,不管是读还是写都是进行加锁.而读写锁会有两种情况: 1.加读锁 2. 加写锁. 读写锁就是一个线程读时,另一个线程只能读不能写. 一个线程写时,另一个线程不能读也不能写. 

1 读锁和读锁之间不会发生堵塞.

2 读锁和写锁之间会发生堵塞.

3 写锁和写锁之间会发生堵塞. 

为什么要引入读写锁

因为多线线程进行读操作,它本身就是线程安全的,但是对于普通互斥锁来说,两个线程读,也会发生锁竞争,堵塞,这就会造成一定的性能损失. 但是对读操作不加锁的话,就怕一个线程读,一个线程写,导致读到的内容不完整.

基于这个情况下就引入了读写锁,它就可以解决对于读操作不加锁的问题.直接将读引发的锁竞争的开销给节省下来了,让性能会有很大的提高. 我们在实际开发中读操作是非常多的,使用读写锁对性能就有明显的提升了.

公平锁与非公平锁

公平锁就是遵循先来后到. 假设A锁先进行锁等待,B锁后进行锁等待.等到其他线程将锁释放后,就是A先获取到锁.

非公平锁就是不管你是先进行等待还是后进行等待.等到其他线程释放锁后.大家都可以竞争这把锁.系统的调度是随机的,下一个唤醒谁都不确定.

站在操作系统的角度上来看待锁,就是不公平锁.因为操作系统调度线程是随机的.下一个将谁调度进来,唤醒谁也不确定.我们Java中的synchronized也是不公平锁.而公平锁就需要引入额外的数据结构.

可重入锁和不可重入锁

可重入锁就是对于一个锁对象来说, 同一个线程可以多次获取到这把锁,不会发生死锁.

不可重入锁就是对于一个锁对象来锁,同一个线程不可以多次获取到这个把锁,不然会发生死锁.

我们的synchronized就是可重入锁,它的内部有两个重要的属性, 一个是用来记录当前持有锁的线程.一个是计数器,一次加锁就+1,一次解锁就-1.当变成0就算彻底解锁成功.

synchronized锁与操作系统自带锁对比

synchronized是:

乐观锁/悲观锁自适应

轻量/重量锁自适应

自旋/挂起等待锁自适应

不公平锁

普通互斥锁

系统自带锁是:

悲观锁

重量级锁

挂起等待锁

不公平锁

普通互斥锁

synchronized的优化策略

锁的升级

synchronized内部会有一个升级阶段.当一个线程执行到synchronized这里时,所对象还没被加锁的时候,就会经历: 1.偏向锁阶段 -> 2.轻量级锁阶段 -> 3.重量级锁阶段

偏向锁阶段(没有其他锁来竞争)

就是在这个需要加锁的线程上做一个轻量的标记,并不会真正的去进行加锁.只有等到其他的线程也要对这个锁进行加锁时.它才会在其他线程获取到锁之前将锁获取过来.这样就从偏向锁升级到了轻量级锁.

这里的核心思想就是懒汉模式.不能加锁就不加锁,迫不得已的情况下再进行加锁.这样就可以在没有其他线程需要加锁的情况下省去加锁的开销.

轻量级锁阶段(有锁竞争,但是不多)

这里的轻量级锁实现的就是自旋锁,这里的优点就是可以很快获取到锁,但是会更消耗CPU资源. synchronized内部会记录当前有多少个线程在竞争这把锁,当超过一个量后,轻量级锁就会升级到重量级锁.

重量级锁阶段(有锁竞争,且很多)

这里的重量级锁实现的就是挂起等待锁,遇到锁冲突后就直接挂起等待,也就是调度出CPU,当释放锁后,让系统随机唤醒一个来获取锁.

锁消除

这里也是编译器优化的一种方式.当发现这个代码不需要加锁时,就会将锁消除掉.

锁粗化

锁粗化就是将多个细粒度的锁合并成一个粗粒度的锁. 这里我们可以理解完synchronized{}里的代码越少粒度就越细.大多数情况下是希望粒度越细越容易并发执行代码,但有的情况下还是希望粒度粗一点.

比如:这里的加锁操作太多就会导致锁竞争的开销过大,每次加锁可能都会堵塞.这时将细粒度的锁变成粗粒度的锁就节省了锁堵塞的开销,也会提高效率.

相关面试题

你是什么理解乐观锁和悲观锁的,具体怎么实现?

乐观锁就是在加锁前认为发生锁冲突的几率不大,在加锁的时候做的工作就不多,就不会真的加锁,而是直接尝试访问数据.在访问数据的同时便辨别当前数据是不是出现访问异常.

悲观锁就是在加锁前认为发生锁冲突的概率比较大,在进行加锁的时候做的工作就比较多,每次访问变量前都会去真正的进行加锁.

悲观锁的实现就是先加锁,获取到锁再来操作数据,获取不到锁就等待.乐观锁的实现可以引入一个版本号,借助版本号识别出当前的数据访问是不是有冲突.

介绍一下读写锁

读写锁就是把读操作和写操作分别进行加锁. 读锁与读锁之间不会发生堵塞. 读锁与写锁之间会发生堵塞.写锁和写锁之间也会发生堵塞. 这就是一个线程读的时候,另一个线程只能读不能写.而一个线程写的时候,另一个线程不能读也不能写. 一般使用读写锁的都是在读非常频繁,但写不频繁的场景下.

synchronized是可重入锁吗

synchronized是可重入锁.可重入锁是指在一个线程内,可以对同一个锁进行多次加锁,不会产生死锁.而synchronized可以重入是因为它内部有两个重要的属性,一个是记录持有这个锁的线程身份,另一个是计数器(记录加锁的次数). 如果发现当前加锁的线程就是持有锁的线程,计数器就会++.

什么是自旋锁,为什么要使用自旋锁呢,缺点是什么?

自旋锁就是当一个线程发生锁竞争后,它不会挂起等待,而是通过while来不断循环来尝试再次获取到锁.一但其他线程释放锁后它就可以立刻获取到锁. 

因为使用自旋锁在第一次获取失败后第二次获取尝试会很快来到,这样就可以快速获取到锁.

优点就是获取锁的速度快,更高效,在锁持有时间比较短且锁竞争小的场景下非常有用,却点就是如果锁竞争多且锁持有时间长的场景下就没有用了且非常浪费CPU资源,因为它一直在不断循环,做的都是无用功.


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

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

相关文章

[css] flex wrap 九宫格布局

<div class"box"><ul class"box-inner"><li>九宫格1</li><li>九宫格2</li><li>九宫格3</li><li>九宫格4</li><li>九宫格5</li><li>九宫格6</li><li>九宫格7&l…

【AI工具】GitHub Copilot IDEA安装与使用

GitHub Copilot是一款AI编程助手&#xff0c;它可以帮助开发者编写代码&#xff0c;提供代码建议和自动完成功能。以下是GitHub Copilot在IDEA中的安装和使用步骤&#xff1a; 安装步骤&#xff1a; 打开IDEA&#xff0c;点击File -> Settings -> Plugins。在搜索框中输…

phpstudy是什么?

PHPStudy 是一个集成环境工具&#xff0c;它将 PHP 开发所需的软件&#xff0c;如 Apache&#xff08;Web服务器&#xff09;、MySQL&#xff08;数据库服务器&#xff09;、PHP&#xff08;脚本语言&#xff09;等打包在一起&#xff0c;以便用户能够轻松安装和配置这些软件&a…

【第1期】SpringSecurity基于角色和权限的细粒度接口权限控制

SpringSecurity 细粒度权限控制 一、Role 和 Authority的区别 角色用来表示某一类权限的集合&#xff0c;权限粒度更小&#xff0c;方便细粒度控制 二、创建用户、角色、权限相关表&#xff1a; CREATE TABLE common_user (id bigint(20) NOT NULL COMMENT 主键id,login_na…

详细教程 - 从零开发 鸿蒙harmonyOS应用 第四节 (鸿蒙Stage模型 登录页面 ArkTS版 推荐使用)

在鸿蒙OS中&#xff0c;Ability是应用程序提供的抽象功能&#xff0c;可以理解为一种功能。在应用程序中&#xff0c;一个页面即一种能力&#xff0c;如登录页面&#xff0c;即具有登录功能的能力。以下是对鸿蒙新建项目的登录代码功能的详细解读和工作流程的描述&#xff1a; …

人工智能在红斑狼疮应用主要以下4个方面

人工智能&#xff08;Artificial Intelligence, AI&#xff09;在医学领域的应用已取得了一定的进展。红斑狼疮&#xff08;Systemic Lupus Erythematosus, SLE&#xff09;是一种免疫系统性疾病&#xff0c;对该疾病进行诊断和治疗是一个复杂的过程。人工智能可以发挥作用&…

棒材生产线的7大智能化提升方向 蓝鹏可定制3大类

轧钢智能化控制体系&#xff0c;实行智能化轧钢&#xff0c;提高产品合格率&#xff0c;满足棒材生产线对于产品精度、生产产量、远程集中操控的需求&#xff0c;是钢厂一直致力于实现的目标&#xff0c;目前可从七大方向对棒材产线的智能化方向进行提升。 棒材生产线有以下智…

CRM客户管理系统-超详细介绍

1. CRM概述 CRM&#xff08;Customer Relationship Management&#xff09;客户关系管理&#xff0c;是一种以客户为中心&#xff0c;通过与客户建立持久的、互惠互利的合作关系&#xff0c;从而提高企业整体绩效的管理方法。CRM系统是支持CRM战略的软件工具&#xff0c;用于…

用Pyinstaller打包深度学习算法为独立的可执行程序

前言&#xff1a;随着深度学习算法的流行&#xff0c;在传统工业软件计算领域&#xff0c;传统算法逐渐被深度学习算法给代替&#xff0c;但由于基于python的深度学习算法十分依赖python环境以及例如Pytorch、Scikit-learning、Keras等机器学习库&#xff0c;将深度学习算法运用…

HarmonyOS4.0从零开始的开发教程17给您的应用添加通知

HarmonyOS&#xff08;十五&#xff09;给您的应用添加通知 通知介绍 通知旨在让用户以合适的方式及时获得有用的新消息&#xff0c;帮助用户高效地处理任务。应用可以通过通知接口发送通知消息&#xff0c;用户可以通过通知栏查看通知内容&#xff0c;也可以点击通知来打开应…

linux 查看服务启动时间

文章目录 linux 查看服务启动时间参数解析 linux 查看服务启动时间 [root104 ~]# ps -o lstart -p ps -ef |grep -v grep |grep "zookeeper"|awk {print$2}STARTED Fri Dec 15 16:54:10 2023参数解析 linux 命令中 ps -ef 详解 ps -ef表示查看全格式的进程。 ps …

UE5 PlaceActor

⚠️ 重点 PlaceActors 需在引擎初始化之后 但&#xff0c;单为这一个功能&#xff0c;更改整个模块的启动顺序&#xff0c;也不太划算 更好的办法是&#xff0c;启动顺序保持正常&#xff08;如"LoadingPhase": "Default" &#xff09;&#xff0c;然后…

超燃超欢乐!修仙喜剧动画《师兄啊师兄》第二季稳健开播

12月14日&#xff0c;备受瞩目的《师兄啊师兄》第二季终于稳健开播&#xff01;首播两集连放&#xff0c;同时第一季全13集限免&#xff0c;不仅便于新观众丝滑入坑&#xff0c;老观众也可以二刷重温&#xff0c;可以说是非常良心了&#xff01; 《师兄啊师兄》改编自人气网络小…

LeetCode(63)旋转链表【链表】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 旋转链表 1.题目 给你一个链表的头节点 head &#xff0c;旋转链表&#xff0c;将链表每个节点向右移动 k 个位置。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], k 2 输出&#xff1a;[4,5,1,2,3]示例 2&…

PE硅芯管抗紫外线和微生物侵害,对水质不会造成任何影响

PE硅芯管是一种优质的管道材料&#xff0c;具有出色的抗紫外线和微生物侵害的能力。这种管道材料采用特殊的生产工艺&#xff0c;添加了硅质材料&#xff0c;从而增强了管道的耐久性。 由于其抗紫外线性能强&#xff0c;PE硅芯管即使在户外长时间暴露于阳光下也不会出现老化、…

基于ssm培训学校教学管理平台论文

摘 要 社会的进步&#xff0c;教育行业发展迅速&#xff0c;人们对教育越来越重视&#xff0c;在当今网络普及的情况下&#xff0c;教学管理模式也开始逐渐网络化&#xff0c;学校开始网络教学管理模式。 本文研究的培训学校教学管理平台基于SSM框架&#xff0c;采用Java技术和…

关于主持知识竞赛的几点体会

知识竞赛被许多人认为不太好主持&#xff0c;因为既然是竞赛&#xff0c;总会有输有赢&#xff0c;而参赛各队又多是有备而来&#xff0c;场上一派剑拔弩张的气势。囿于这样的气氛中&#xff0c;再加上知识竞赛的固定模式&#xff0c;主持人很难有所发挥&#xff0c;因此&#…

6个超好用的小众图片素材网站,高清、免费,值得收藏~

推荐几个超好用的图片素材网站&#xff0c;免费下载&#xff0c;还可以商用&#xff0c;建议收藏哦~ 1、菜鸟图库 https://www.sucai999.com/pic.html?vNTYwNDUx 我推荐过很多次的设计素材网站&#xff0c;除了设计类素材&#xff0c;还有很多自媒体可以用到的高清图片、背景…

win11装了Ubuntu系统,切换到 wim11,蓝牙耳机显示已连接,但耳机无声音,且声音外放正常

打开 设置>蓝牙和其它设备 &#xff0c;发现耳机是连接正常的&#xff0c;点击页面的 设备 发现蓝牙耳机已经被识别音频&#xff0c;也可能没有被识别为音频设备&#xff0c;而是显示其他设备&#xff0c;这样会导致输出设备上没有耳机这一选项&#xff0c;则点击设备和打印…

当你在浏览器中键入“https://www.google.com”并按 Enter 键时会发生什么?

互联网是我们每天使用的奇迹&#xff0c;在其表面之下隐藏着一层层的复杂性。有没有想过当你输入一个URL时&#xff0c;幕后会发生什么&#xff1f;今天&#xff0c;让我们满足我们的好奇心&#xff0c;揭开由一个简单的命令启动的错综复杂的进程网络&#xff1a;键入“https:/…