【多线程】乐观/悲观锁、重量级/轻量级锁、挂起等待/自旋锁、公平/非公锁、可重入/不可重入锁、读写锁

文章目录

  • 乐观锁和悲观锁
  • 重量级锁和轻量级锁
  • 挂起等待锁和自旋锁
  • 公平锁和非公平锁
  • 可重入锁和不可重入锁
  • 读写锁
  • 相关面试题

:非常广义的概念,不是指某个具体的锁,所有的锁都可以往这些策略中套
synchronized:只是市面上五花八门的锁种,其中一种典型的实现,Java 内置的,推荐使用的锁

乐观锁和悲观锁

这两个词不是指某个具体的锁,而是锁的一种“特性”,描述了“一类”

乐观锁:加锁的时候,假设出现冲突的概率不大

  • 接下来围绕加锁要做的工作就会更少
    悲观锁:加锁的时候,假设出现锁冲突的概率很大
  • 接下来围绕加锁要做的工作就会更多

使用 synchronized,初始情况下,是乐观的(预估接下来锁冲突概率不大)

  • 同时会在背后偷偷地统计锁冲突了多少次
  • 如果发现锁冲突达到一定程度了,就会转变为“悲观的”
    乐观锁和悲观锁需要做的事情是不同的
  • 乐观做的事情少一点
  • 悲观做的事情往往更重量级

站在预测锁冲突的概率是否高
synchronized 是自适应的

重量级锁和轻量级锁

效果和悲观乐观是重叠的,只是站在的角度不一样

重量级锁:加锁的开销比较大,要做的工作更多

  • 往往悲观的时候,会做的
    轻量级锁:加锁的开销比较小,要做的工作相对更少
  • 往往乐观的时候,会做的
    但也不能认为是 100%等价,因为:
  • 乐观和悲观是站在“预估所冲突”角度
  • 重量轻量是站在“加锁开销“角度

站在加锁的开销角度
synchronized 也是自适应的

挂起等待锁和自旋锁

挂起等待锁:属于是悲观锁/重量级锁的一种典型实现
自旋锁:乐观锁/轻量级锁的一种典型实现

比如:
你去追你的女神:
女神女神,我好喜欢你,

  • 你尝试对女神加锁
    女神表示:我有男朋友了

  • 女神表示她这把锁已经被别的线程给加了
    你就可以选择“等待”,等到女神锁被释放,比如:

  • 你选择每天仍然会给女神不停地问候“早安,午安…”,这里的行为称为“自旋锁

    • 这里的等待是“忙等”,等待的过程中 CPU 的资源不会释放
    • 某天女神和男朋友吵架了,不开心,你就立刻能感知到,机会来了。这样你就可以在女神锁释放的第一时间,立刻抓住机会,能够上位
    • 不停地,循环地检测锁是否被释放,一旦锁释放,就能立即有机会能获得锁
  • 你选择把女神拉黑,先不联系了,若干年后你从别人那里听说,女神分手了,你再去联络女神,这种行为就是“挂起等待锁

    • 不联系,就相当于“让出 CPU 资源”CPU 就可以去做别的事了
    • 不理女神之后,我们就可以有心思好好学习,好好敲代码,好好找工作了,在过程中做成更多的事情。过了一段时间后,我们通过一些途径听说女神分手了,再伺机而动,但“听说”的时效性很低,这个中间可能有很长的时间跨度。在这个时间跨度里,女神是否由谈了男朋友?分手了多少次?你是不知道的
    • 挂机时间更长,但能节省下 CPU 资源去做别的事情

注意:

  • 只有在假定锁冲突概率不高的情况下,才能“忙等”。如果好几个线程都在竞争同一个锁,一个线程拿到锁,其他的都在“忙等”,这样总的 CPU 消耗就会非常高
  • 而且,由于竞争太激烈,导致有些线程要等待很久才能拿到锁
  • 锁冲突很高的概率很高的话就不适合“自旋锁”方案

  • 挂起等待锁也就适合“悲观锁”这样的场景了
  • 锁竞争非常激烈,预测拿到锁的概率本身就不打,不放吧 CPU 让出来,充分的做其他事情

synchronized“自适应”

  • 轻量级锁就是基于自旋的方式实现的(JVM 内部,用户态代码实现)
  • 重量级锁就是基于挂起等待的方式实现的(调用操作系统 API,在内核中实现)
    纯用户态代码往往执行效率比内核态代码的高一些,总体来说,我们还是认为“自旋”的效率更高的,但是 CPU 开销更大
    挂起等待锁的操作虽然 CPU 开销变少了,但整体的等待时间更多

公平锁和非公平锁

日常生活中,说的公平可能有不同的含义


image.png|521
当女神分手了,该轮到谁上位呢?

公平锁: 在计算机中,约定“先来后到”为公平
image.png|556


非公平锁: 系统原生
image.png|365


synchronized 属于非公平锁

  • N 个线程竞争同一个锁,其中一个线程拿到锁了,后续该线程释放锁之后,剩下的 N-1 个线程,就要重新竞争锁,谁能拿到锁,就不一定了
  • 当然,也不能保证这些线程竞争中获取的概率一定是数学上的严格均等
    本身操作系统内核里针对锁的处理就是如此,synchronized 在系统内核的基础上,没有做啥额外的操作

如需要使用公平锁,就需要做额外的工作

  • 比如引入队列,记录每个线程加锁的顺序

可重入锁和不可重入锁

死锁问题:如果一个线程,针对同一把锁,连续加锁两次,就可能出现死锁,如果把锁设为“可重入”就可以避免死锁了

可重入:是专门的计算机术语,不要写作“可重复”这样的词

可重入锁

  • 会记录当前是哪个线程持有了这把锁
  • 在加锁的时候判定,当前申请锁的线程,是否就是锁的持有者
  • 计数器,记录加锁的次数,从而确定何时真正释放锁
    • 遇到一个 { 加一次锁,计数器加一
    • 遇到一个 } 解锁一次,计数器减一
    • 等到计数器为零,真正释放锁

读写锁

synchronized 并非是读写锁
所谓的读写锁,把“加锁操作”分为两种情况

  • 读加锁
  • 写加锁
    如果多个线程同时读这个变量,没有线程安全问题,但是
  • 一个线程读/一个线程写
  • 两个线程都写
    就会产生问题

在实际开发中,在大部分场景下,读操作的频次,本身就比写操作的频次高。所以就让读操作不产生锁冲突,这样就只有少数写操作会产生冲突,这样效率就高了


读写锁提供了两种加锁的 API,系统内置的锁,Java 标准库中的读写锁类为:ReentrantReadWriteLock

  • 加读锁
    • ReentrantReadWriteLock 的内部类 ReentrantReadWriteLock.ReadLock 表示加读锁,这个对象提供了 lock/unlock ⽅法进⾏加锁解锁
  • 加写锁
    • ReentrantReadWriteLock 的内部类 ReentrantReadWriteLock.WriteLock 表示加写锁,这个对象也提供了lock/unlock ⽅法进⾏加锁解锁
      解锁的 API 是一样的,就需要把 unlock 放到 finally 中,确保能够执行到
  • 如果两个线程都是按照读方式加锁,此时不会产生锁冲突;
  • 如果两个线程都是家写锁,此时会产生锁冲突
  • 如果一个线程读锁,一个线程写锁,也会产生冲突

相关面试题

image.png


image.png


image.png


image.png

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[独家原创]基于分位数回归的Bayes-GRU多变量时序预测【区间预测】 (多输入单输出)Matlab代码

[独家原创]基于分位数回归的Bayes-GRU多变量时序预测【区间预测】 (多输入单输出)Matlab代码 目录 [独家原创]基于分位数回归的Bayes-GRU多变量时序预测【区间预测】 (多输入单输出)Matlab代码效果一览基本介绍程序设计参考资料 效…

RM麦轮控制以及底盘解算

一个典型的RM机器人四轮底盘由电机,底板,悬挂等构成,底盘安装在底盘的四角,呈矩形分布,麦克纳姆轮的辊子方向会影响其运动性能,一般采用如下图所示,四个麦轮的辊子延长线都过底盘中心的安装方法…

c语言学习,atoi()函数分析

1:atoi() 函数说明: 检查参数*ptr,子串中数字或正负号,遇到非数字或结束符停止 2:函数原型: int atoi(const char *ptr) 3:函数参数: 参数c,为检测子串 4:…

MyBatis 配置与测试方式

目录 一,什么是MyBatis 二,准备工作 创建项目 配置数据库连接 持久层代码 单元测试 一,什么是MyBatis 简单来说,MyBatis 是一款优秀的持久层框架,用于简化JDBC的开发,能更简单完成程序与数据库之间…

从0到1,AI我来了- (5)大模型-本地知识库-I

一、下载&安装Ollama Ollama下载地址: Download Ollama on macOS Github地址:GitHub - ollama/ollama: Get up and running with Llama 3.1, Mistral, Gemma 2, and other large language models. Ollama 是啥? 是一个人工智能和机器学习…

一文搞懂后端面试之不停机数据迁移【中间件 | 数据库 | MySQL | 数据一致性】

数据迁移方面的工作: 重构老系统:使用新的表结构来存储数据单库拆分分库分表、分库分表扩容大表修改表结构定义 数据备份工具 MySQL上常用的两款数据备份工具:mysqldump和XtraBackup mysqldump:一个用于备份和恢复数据库的命令…

Redis中的set类型

set的含义 集合设置(和get相对应) 集合就是把一些有关联的数据放到一起 集合中的元素是无序的(和list的有序是对应的-顺序很重要,这里的无序就是顺序不重要);在list中[]1,2,3],[1,3,2],是两个…

Java开发工具IDEA

IDEA概述 Intellij IDEA IDEA全称Intellij IDEA,是用于Java语言开发的集成环境,它是业界公认的目前用于Java程序开发最好的工具。 集成环境 把代码编写,编译,执行,调试等多种功能综合到一起的开发工具。 IDEA下载和安…

PDF在线预览实现:如何使用vue-pdf-embed实现前端PDF在线阅读

目录 PDF在线预览实现:如何使用vue-pdf-embed实现前端PDF在线阅读 一、前言 二、vue-pdf-embed是什么 1、作用与场景 2、vue-pdf-embed的优点 三、项目初始化与依赖安装 1、初始化Vue项目 2、安装依赖 3、集成vue-pdf-embed插件 四、一个实际的应用demo …

Java面试题精选:消息队列(一)

1、为什么使用消息队列 问题用意: 其实就是想问一下消息队列有哪些使用场景,你项目中什么业务场景用到了消息队列,有什么技术挑战。使用MQ后给你带来了什么好处 规范回答: 消息队列的常见使用场景很多,但比较核心的…

【漏洞修复】Tomcat中间件漏洞

1.CVE-2017-12615 抓包上传一句话木马 密码passwd 2.后台弱口令部署war包 先用弱口令登录网站后台 制作war包 将172.jsp压缩成.zip文件,修改后缀为.war 上传 蚁剑链接 3.CVE-2020-1938 Python2 CVE-2020-1938.py IP -p 端口 -f 要读取的文件 漏洞修复&#xf…

超越自我——带你学haproxy算法一遍过!!!

文章目录 前言介绍 静态算法static-rrfirst 动态算法roundrobinleastconn 其他算法source算法map-base 取模法一致性hashuriurI_param 取模法hdr 总结本文相关连接如下: 前言 本文相关连接如下: 如果想更多了解haproxy的相关知识,请点击&am…

HTTP协议和运行原理

HTTP 是一个在计算机世界里专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范。不仅仅适用于[服务器<–>客户端]也是适用于[服务器<–>服务器] HTTP 状态码 1xx 1xx 类状态码属于提示信息&#xff0c;是协议处理中的一种中间状态&#xff0c;实际…

操作系统 IO 相关知识

操作系统 IO 相关知识 阻塞与非阻塞同步与异步IO 和系统调用传统的 IODMAmmap 内存映射sendfilesplice 常用的 IO 模型BIO&#xff1a;同步阻塞 IONIO&#xff1a;同步非阻塞 IOIO 多路复用信号驱动 IOAIO&#xff1a;异步 IO 模型 IO 就是计算机内部与外部进行数据传输的过程&…

加密案例分享:电子设备制造行业

企业核心诉求选择 1.某企业规模庞大&#xff0c;分支众多&#xff0c;数据安全管理方面极为复杂&#xff1b; 2.企业结构复杂&#xff0c;包括研发、销售、财务、总部、分部、办事处、销售等单位连结成为一个庞大的企业组织&#xff0c;数据产生、存储、流转、使用、销毁变化…

NIO线程模型

NIO线程模型主要涉及以下几个方面&#xff1a; 一、基本概念 NIO&#xff08;New Input/Output&#xff09;是Java的一种新的输入输出模型&#xff0c;也被称为非阻塞IO。其核心特点是数据读写操作均是非阻塞的&#xff0c;即在进行读写操作时&#xff0c;若数据未准备好&…

第129天:内网安全-横向移动WmiSmbCrackMapExecProxyChainsImpacket

这里这个环境继续上一篇文章搭建的环境 案例一&#xff1a; 域横向移动-WMI-自带&命令&套件&插件 首先上线win2008 首先提权到system权限 wmic是windows自带的命令&#xff0c;可以通过135端口进行连接利用&#xff0c;只支持明文方式&#xff0c;优点是不用上传别…

【区块链+医疗健康】医链 - 区块链医疗信息管理系统 | FISCO BCOS应用案例

根据《“十四五”规划和 2035 远景目标纲要》&#xff0c;我国在“十四五”时期将全面推进医疗信息化建设。工信部等部 门联合发布《关于加快推动区块链技术应用和产业发展的指导意见》&#xff0c;促进区块链在医疗健康等公共服务领域开 展应用&#xff0c;促进业务协同办理。…

ES6 export import

1.Export 模块是独立的文件&#xff0c;该文件内部的所有的变量外部都无法获取。如果希望获取某个变量&#xff0c;必须通过export输出&#xff0c; 声明的同时导出变量、函数以及类 // profile.js export var firstName Michael; export var lastName Jackson; export var…

【JUC】Java对象内存布局和对象头

文章目录 面试题Object object new Object() 谈谈你对这句话的理解&#xff1f; 对象在堆内存中存储布局权威定义&#xff08;周志明老师JVM第三版&#xff09;对象在堆内存中的存储布局详解对象头的MarkWord源码对象标记源码 对象内存布局&#xff08;使用JOL证明&#xff09…