javaEE 初阶 — 常见的锁策略

news2025/1/23 4:00:32

文章目录

  • 1. 乐观锁 vs 悲观锁
  • 2. 互斥锁 vs 读写锁
  • 3. 重量级锁 vs 轻量级锁
  • 4. 自旋锁 vs 挂起等待锁
  • 5. 公平锁 vs 非公平锁
  • 6. 可重入锁 vs 不可重入锁
  • 7. synchronized 是哪种锁
  • 8. 相关面试题

1. 乐观锁 vs 悲观锁


乐观锁 指的是预测锁竞争不是很激烈,也就是指这里做的工作相对较少。
悲观锁 指的是预测锁竞争会很激烈,也就是指指这里做的工作相对多一点。

悲观和乐观都不是绝对的,主要就是看预测锁竞争激烈程度的结论。


这两个锁是站在冲突概率的预测角度。

2. 互斥锁 vs 读写锁


互斥锁 就是之前使用的 synchronized 这样的锁,提供 加锁 和 解锁 两个操作。
如果一个线程加锁了,另一个线程也尝试加锁,就会阻塞等待。

读写锁 提供了三种操作:

  • 针对读加锁
  • 针对写加锁
  • 解锁

基于一个事实:

多线程针对同一个变量并发读,这个时候是没有线程安全问题的,也不需要加锁控制。
读写锁 就是针对这种情况所采取的特殊处理。

当前的代码中,如果只是读操作,就加读锁即可,如果有写操作,就加写锁。

  • 读锁读锁 之间没有互斥
  • 写锁写锁 之间存在互斥
  • 写锁读锁 之间存在互斥

如果当前有一组线程都去读(加读锁),此时这些线程之间是没有锁竞争和线程安全问题的。
如果当前有一组操作有读也有写,才会有竞争问题。

另一个事实:

在很多开发场景中,读操作的频率比写操作的频率高很多。

3. 重量级锁 vs 轻量级锁


轻量级锁 加锁解锁开销比较小,效率更高;重量级锁 加锁解锁开销比较大,效率更低。

多数情况下,乐观锁也是一个轻量级锁(不能完全保证)
多数情况下,悲观锁也是一个重量级锁(不能完全保证)

这两个锁是站在加锁操作的开销角度。

4. 自旋锁 vs 挂起等待锁


自旋锁 是一种典型的轻量级锁,挂起等待锁 是一种典型的重量级锁。

举一个例子

张三要向一个女生表白,此时就是张三尝试对这个女生加锁。
但是女生说她有男友了,也就是说明她被别人加锁了。

如果张三还不死心,为了找一个机会上位,此时就有两种等待的方式。

  • 自旋锁:
    张三没有都在女生身边转悠,一旦女生分手了,就能第一时间知道。
    而一旦锁被释放就能第一时间感知到,从而有机会获取到锁,很明显,自旋锁占用了大量的资源

  • 挂起等待锁:
    张三愿意等女生分手,张三就悄悄地等着,也不会去打扰那个女生。
    当女生分手的时候,有可能会想起张三,也有可能不会。但是更大的概率,女生会把张三也忘记了。
    当真的被唤醒的时候,不知道过了多长时间。
    此时就是把 CPU 省下来了,就可以干别的事情了。

5. 公平锁 vs 非公平锁


此处的公平定义为 “先来后到”

举个例子



女神现在已经被别人加锁了,1号老铁已经阻塞等待一年了,2号老铁阻塞等待一个月了,
而3号老铁从昨天才开始阻塞等待的。

公平锁 就是当女神分手的时候,最先开始追女神的1号老铁先和女神谈恋爱,
后续老铁等女神再次分手才可以和女神谈恋爱。



非公平锁 就是 “雨露均沾” 的意思。



当女神分手的时候,三个老铁一起上,公平竞争。
最早开始追女神的1号老铁所付出的时间和精力都比其他两个老铁要多,这是就不那么公平了。

就好比某个企业有一个晋升的名额,此时应该采取的是 “先来后到” 的方式才公平。
因为先来的员工工作时间长,对公司的贡献比较大,而不应该 “雨露均沾” 的方式,
有的员工工作时间长,有的工作时间短,这样就不公平了。

操作系统和 java synchronized 元素都是 “非公平锁”
操作系统这里的针对加锁的控制,本身就依赖于线程调度顺序的。
这个调度顺序是随机的,不会考虑到这个线程等待锁多久了。

要想实现公平锁,就得在这个基础上,能够引入额外的东西。
(引入一个队列,让这些加锁的线程去排队)

但是引入额外的队列又有额外的开销和代码上成本。

6. 可重入锁 vs 不可重入锁


可重入锁 :一个线程针对一把锁,连续多次加锁都不会死锁。

不可重入锁 :一个线程针对一把锁,连续两次加锁会出现死锁。

7. synchronized 是哪种锁


1、synchronized 既是一个 悲观锁 又是一个 乐观锁

synchronized 默认是乐观锁,但是如果发现当前的锁竞争比较激烈,就会变成悲观锁。


2、synchronized 即是 轻量级锁 又是 重量级锁

synchronized 默认是轻量级锁,但是如果发现当前的锁竞争比较激烈,就会变成重量级锁。


3、synchronized 这里的轻量级锁,是基于 自旋锁 的方式实现的。synchronized 这里的重量级锁,是基于挂起等待锁的方式实现的。


4、synchronized 不是 读写锁


5、synchronized 是 非公平锁


6、synchronized 是 可重入锁

8. 相关面试题


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

悲观锁 认为多个线程访问同一个共享变量冲突的概率较大,会在每次访问共享变量之前都去真正加锁。

乐观锁 认为多个线程访问同一个共享变量冲突的概率不大。并不会真的加锁, 而是直接尝试访问数
据。在访问的同时识别当前的数据是否出现访问冲突。

悲观锁 的实现就是先加锁(比如借助操作系统提供的 mutex),获取到锁再操作数据。
获取不到锁就等待。

乐观锁 的实现可以引入一个版本号,借助版本号识别出当前的数据访问是否冲突。


2、介绍下读写锁?

读写锁就是把读操作和写操作分别进行加锁.

  • 读锁和读锁之间不互斥
  • 写锁和写锁之间互斥
  • 写锁和读锁之间互斥

读写锁最主要用在 “频繁读,不频繁写” 的场景中


3、什么是自旋锁,为什么要使用自旋锁策略呢,缺点是什么?

如果获取锁失败,立即再尝试获取锁,无限循环,直到获取到锁为止。
第一次获取锁失败,第二次的尝试会在极短的时间内到来。一旦锁被其他线程释放,就能第一时间获取到锁。

相比于挂起等待锁:

优点:

没有放弃 CPU 资源,一旦锁被释放就能第一时间获取到锁,更高效,在锁持有时间比较短的场
景下非常有用。

缺点:如果锁的持有时间较长, 就会浪费 CPU 资源


4、synchronized 是可重入锁么?

是可重入锁。

可重入锁指的就是连续两次加锁不会导致死锁。

实现的方式是在锁中记录该锁持有的线程身份,以及一个计数器(记录加锁次数)。
如果发现当前加锁的线程就是持有锁的线程,则直接计数自增。

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

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

相关文章

排列组合两个列表中的元素 product(a,b)

【小白从小学Python、C、Java】【计算机等级考试500强双证书】【Python-数据分析】排列组合两个列表中的元素product(a,b)关于以下python代码表述错误的一项是?from itertools import producta [1,2,3]b [4,5,6]print("【显示】a",a)print("【显示】b",…

修改Keil开发环境背景(修改为黑色主题)

修改Keil开发背景(修改为黑色主题)引言步骤总结引言 我们平时在Keil uVision5下开发单片机/嵌入式程序的时候,如果始终用的是官方的主题背景,往往会因为背景太白了,而导致视疲劳。我们使用VSCode往往不会有这种困扰&a…

Python处理字符串 中文(汉字)编码示例

在实际开发中,发现打印Python打印经常出现乱码,大部分都是编码引起,这里只是简单说一下utf-8/ gbk/ unicode编码之间的相互转换问题: utf-8是Unix下的一种通用编码,gbk是win环境下的一种汉字编码,unicode是…

计算机组成原理_总线仲裁

计算机组成原理总目录总线仲裁 由于总线连接着多个设备,那么在同一时刻多个设备想要占用总线时,就会发生冲突问题 为了解决冲突问题,就需要规定好所有设备使用设备的优先权,仲裁也就是判断设备占用总线的优先权 例如设备A的任务比…

Docker--安装mysql8--方法/步骤

原文网址:Docker--安装mysql8--方法/步骤_IT利刃出鞘的博客-CSDN博客 简介 本文介绍如何使用docker安装mysql8。 查看mysql版本 https://hub.docker.com/_/mysql/tags 我选择8.0,点击右侧箭头处直接复制命令。 拉取镜像 拉取镜像的命令 docker pul…

RADIANT:一种全新的雷达图像关联网络用于3D目标检测

RADIANT:一种全新的雷达图像关联网络用于3D目标检测 论文地址:RADIANT: Radar-Image Association Network for 3D Object Detection 源码:https://github.com/longyunf/radiant 单位:密歇根大学、福特 动机 作为一种能够直接…

全景剖析阿里云容器网络数据链路(二):Terway EN

作者:余凯 本系列文章由余凯执笔创作,联合作者:阿里云容器服务 谢石 对本文亦有贡献 前言 近几年,企业基础设施云原生化的趋势越来越强烈,从最开始的 IaaS 化到现在的微服务化,客户的颗粒度精细化和可观…

使用小度音箱+Blinker控制ESP01S Relay继电器模块

一. 使用ESP01S模块,PIN脚定义如下: 管脚功能如下: ESP01S模块原理图: ESP01S模块比ESP01模块做了以下优化: LED灯的管脚发生变化,由ESP01的TXD0变成ESP01s的GPIO2引脚;ESP01s模块的IO0、RST、…

Java开发 - Spring MVC框架初体验

前言 上一篇Spring框架感觉写的偏向于理论知识,所以从这篇开始,转变此系列的写作思维,更多的将从实操的角度来讲解Spring MVC框架的使用和相关知识点,会尽量详细,但这一系列课程针对的还是有Java基础的小伙伴&#xf…

树莓派上如何安装anaconda/miniconda环境配置

目录1. 前言2. miniconda下载3. miniconda 安装4. 添加 .bashrc 配置5. Conda 更换源,软件更新6. 部分问题及解决方案报错一:报错二:报错三:7. 卸载miniconda8. 版本问题/注意事项1. 前言 在装完树莓派之后,当你想要使…

()智能指针一) shared_ptr

智能指针(一) 文章目录智能指针(一)shared_ptr1初始化方式make_ptr<>() 和 shared_ptr<>() 的区别shared_ptr维护引用计数需要的信息使用原始的new函数创建shared_ptr使用make_shared创建shared_ptrmake_shared实现异常安全使用make_shared的缺点make_shared 源码解…

从一个Demo说起Dubbo3

简介 2017年的9月份&#xff0c;阿里宣布重启Dubbo的开发维护&#xff0c;并且后续又将Dubbo捐献给了Apache&#xff0c;经过多年的发展已经发布到3.X版本了&#xff0c;Dubbo重启维护之后是否有值得我们期待的功能呢&#xff0c;下面就来看看吧。 Apache Dubbo 是一款微服务…

买英伟达RTX 30 系显卡送《穿越火线》大礼包,你心动了吗?

2022年下半年英伟达一口气推出了RTX 4090、4080、4070 Ti显卡&#xff0c;40系列中的4060也在准备中&#xff0c;而RTX 30 系列在新系列的光芒下显得有些暗淡。 面对40系列即将成为主流的这种情况下&#xff0c;英伟达势必要想一些办法清清30系列显卡的库存&#xff0c;于是英…

上半年要写的博客文章24

上半年要写的博客文章21 这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个…

网络工程师备考6章(续3)

6.20 距离矢量路协议与RIP 动态路由协议的第一个分类:距离矢量和链路状态 什么是距离矢量,例如我要从成都自驾去北京,不知道怎么走,决定路径的方式可以问别人怎么到西安,到西安后再问别人下一条路径,怎么到郑州,到郑州再问别人。一跳一跳的不停问别人,类似于距离矢量协…

P2- 复信号 - 通讯原理

前言&#xff1a; 这里主要结合一下欧拉定理,介绍一下复信号 一 复数概念定义 复数有两种定义方式&#xff1a; 指数函数&#xff1a;&#xff08;通过欧拉公式展开可以得到对应的复数形式&#xff09; 复数&#xff1a;实部a, 虚部b 幅值:A 相位: 二 复信号 2.1 定义 复信…

深度学习程序的预处理

目录 引入 1、预定义符号 1、为什么oj的编译器是clang和gcc呐&#xff1f; 1、vs测试 2、gcc测试 2、#define 1、#define定义标识符 1、#define的花样使用 2、续行符\的使用 3、预处理文件的内容展示和为什么头文件不能重复包含 4、vs下如何生成预处理后的文件&#xff1…

高分综述:人类肠道病毒组分类的进展和挑战

期刊&#xff1a;Cell Host Microbe 影响因子&#xff1a;31.316发表时间&#xff1a;2022.7 - 一、摘要 -人类肠道病毒组通常被称为肠道微生物组的“暗物质”&#xff0c;仍未得到充分研究。了解不同人群肠道病毒组的组成和变化对于探索其对人类健康的影响至关重要。人类肠道病…

聊透Spring事件机制

1、概述 事件机制是Spring为企业级开发提供的神兵利器之一&#xff0c;它提供了一种低耦合、无侵入的解决方式。 但其实Spring事件的设计其实并不复杂&#xff0c;它由三部分组成&#xff1a;事件、发布器、监听器。事件是主体&#xff0c;发布器负责发布事件&#xff0c;监听…

Lottie简介 + 结合到vue3中使用

Lottie简介 结合封装到vue3中使用前言&#xff1a;一、Lottie是什么1. 官方介绍2. 实现流程3. 动画资源二、为什么要选择Lottie三、lottie-web的使用1. 安装导入2. 初始化动画实例3. lottie-web支持的控制动画的主要方法4. lottie-web支持的监听动画的常用的事件四、lottie-we…