当前位置: 首页 > news >正文

Java Web 实战 11 - 多线程进阶之常见的锁策略

常见的锁策略

  • 常见的锁策略
    • 1. 乐观锁 VS 悲观锁
    • 2. 普通的互斥锁 VS 读写锁
    • 3. 重量级锁 VS 轻量级锁
    • 4. 自旋锁 VS 挂起等待锁
    • 5. 公平锁 VS 非公平锁
    • 6. 可重入锁 vs 不可重入锁
    • 7. 常见面试题

大家好 , 这篇文章给大家带来的是多线程中常见的锁策略 , 我们会给大家讲解 6 种类别的锁

  1. 乐观锁 VS 悲观锁
  2. 普通的互斥锁 VS 读写锁
  3. 重量级锁 VS 轻量级锁
  4. 自旋锁 VS 挂起等待锁
  5. 公平锁 VS 非公平锁
  6. 可重入锁 vs 不可重入锁
  7. 常见面试题

针对常见的锁策略 , 这就属于面试爱考但是工作用不上的内容了
大家理解记忆即可
推荐大家跳转到这观看效果更佳
上一篇文章的链接我也给大家贴到这里了

小狗说要请大家喝饮料 , 快跟我说 : “谢谢小狗”
在这里插入图片描述
在这里插入图片描述

常见的锁策略

锁策略指的是 : 加锁的时候我们咋加的
这里说的锁策略 , 和语言基本无关 , 其他的语言也涉及到 “锁策略”

1. 乐观锁 VS 悲观锁

乐观锁 : 预测接下来锁冲突的概率不大 , 就需要做一类操作
悲观锁 : 预测接下来锁冲突的概率很大, 就需要做另一类操作

举个栗子 :
疫情导致封校了
有的人就比较紧张 , 去超市抓紧屯点零食 -> 乐观锁
有的人就无所谓 , 饿不死就行 -> 悲观锁
针对预测的结果不同 , 解决的方法不同

乐观锁相对来说 , 成本更小 ; 悲观锁相对来说 , 成本更大

我们之前介绍过 synchronized , 它既是悲观锁 , 又是乐观锁 , 也就是自适应锁
当前锁冲突概率不大 , 以乐观锁的方式运行 , 往往是纯用户态执行的
一旦发现锁冲突大了 , 以悲观锁的方式运行 , 往往要进入内核 , 对当前线程进行挂起等待

2. 普通的互斥锁 VS 读写锁

synchronized 就是普通的互斥锁 , 两个加锁操作会产生竞争

读写锁把加锁操作进行细化了 , 分成了 “加读锁” 和 “加写锁”
情况1 :
线程 A 尝试加写锁
线程 B 尝试加写锁
线程 A 和 线程 B 产生竞争 , 和普通的锁没啥区别
情况 2 :
线程 A 尝试加读锁
线程 B 尝试加读锁
线程 A 和 线程 B 不产生竞争 , 锁相当于没加一样
(多线程读 , 不涉及修改 , 是线程安全的)
情况 3 :
线程 A 尝试加读锁
线程 B 尝试加写锁
线程 A 和线程 B 产生竞争 , 和普通的锁没什么区别

只有情况 2 (两个线程都是加读锁) 是线程安全的

读写锁就是把读操作和写操作区分对待 , Java 标准库提供了 ReentrantReadWriteLock类 , 实现了读写
锁.

  • ReentrantReadWriteLock.ReadLock 类表示一个读锁 . 这个对象提供了 lock / unlock方法进行加锁解锁 .
  • ReentrantReadWriteLock.WriteLock 类表示一个写锁 . 这个对象也提供了 lock / unlock方法进行加锁解锁 .

3. 重量级锁 VS 轻量级锁

重量级锁指的是锁的开销比较大 , 做的工作比较多
轻量级锁指的是锁的开销比较小 , 做的工作比较少

悲观锁 , 经常会是重量级锁
乐观锁 , 经常会是轻量级锁
但是不是绝对的

那什么叫做 做的工作多 , 做的工作少呢 ?
我们一般认为 , 锁这个东西要保持互斥的 , 那保持互斥要有力量来源的
我们 Java 中实现一把锁 , 需要使用 synchronized 关键字 (后续还会降解 ReentrantLock)
那 Java 里面实现锁 , 主要是 JVM 提供的 synchronized 和 ReentrantLock 这两个机制
那 JVM 之所以能够实现锁机制 , 是因为操作系统提供了 mutex 互斥锁
操作系统之所以能够加锁 , 是因为 CPU 提供了一些用来加锁的 , 能够保证原子操作的指令
image.png
重量级锁主要是依赖了操作系统提供的锁 , 使用操作系统提供的锁 , 就很容易产生阻塞等待
轻量级锁主要是尽量的避免使用操作系统提供的锁 , 尽量在用户态完成功能 , 也就是尽量的避免用户态和内核态的切换 , 尽量避免挂起等待 (阻塞等待)

synchronized 是自适应锁 , 既是轻量级锁 , 又是重量级锁
也是根据锁冲突的情况来决定的
冲突的不高就是轻量级锁 , 冲突的很高就是重量级锁

4. 自旋锁 VS 挂起等待锁

自旋锁和挂起等待锁是更加深入来看的 , 相当于分析的最内层

自旋锁 : 当我们发现锁冲突的时候 , 不会挂起等待 , 它会迅速再次尝试这个锁能不能获取到 (超级舔狗)
他就相当于是一个 while 循环一直获取锁的状态
一旦锁被释放 , 就可以第一时间获取到
如果锁一直不释放 , 就会消耗大量的 CPU
自旋锁是更加轻量的 , 效率更高的

挂起等待锁 : 发现锁冲突 , 就挂起等待
一旦锁被释放 , 不能第一时间获取到
在锁被其他线程占用的时候 , 会放弃 CPU 资源
挂起等待锁是更加重量的 , 效率更低的

自旋锁 , 是轻量级锁的具体实现
挂起等待锁 , 是重量级锁的具体实现

自旋锁是轻量级锁 , 也是乐观锁
挂起等待锁是重量级锁 , 也是悲观锁

synchronized 作为轻量级锁的时候 , 内部是自旋锁
synchronized 作为重量级锁的时候 , 内部是挂起等待锁

5. 公平锁 VS 非公平锁

啥样的情况才算是公平呢 ?
符合 “先来后到” 这样的规则 , 就是公平

先来的 , 先排在前面 . 来晚的 , 就在后面排着

举个栗子 :
image.png
操作系统中 , 默认的锁的竞争规则 , 就是非公平的 , 没有考虑先来后到
如果要想使用公平锁 , 就需要使用额外的数据结构来进行控制实现
所以 synchronized 是非公平锁

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

image.png

7. 常见面试题

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

悲观锁认为多个线程访问同一个共享变量冲突的概率较大, 会在每次访问共享变量之前都去真正加锁.
乐观锁认为多个线程访问同一个共享变量冲突的概率不大. 并不会真的加锁, 而是直接尝试访问数据. 在访问的同时识别当前的数据是否出现访问冲突.
悲观锁的实现就是先加锁(比如借助操作系统提供的 mutex), 获取到锁再操作数据. 获取不到锁就等待.
乐观锁的实现可以引入一个版本号. 借助版本号识别出当前的数据访问是否冲突. (实现细节参考上面的图).

  1. 介绍下读写锁?

读写锁就是把读操作和写操作分别进行加锁.
读锁和读锁之间不互斥.
写锁和写锁之间互斥.
写锁和读锁之间互斥.
读写锁最主要用在 “频繁读, 不频繁写” 的场景中.

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

如果获取锁失败, 立即再尝试获取锁, 无限循环, 直到获取到锁为止. 第一次获取锁失败, 第二次的尝试会在极短的时间内到来. 一旦锁被其他线程释放, 就能第一时间获取到锁.
相比于挂起等待锁,
优点: 没有放弃 CPU 资源, 一旦锁被释放就能第一时间获取到锁, 更高效. 在锁持有时间比较短的场景下非常有用.
缺点: 如果锁的持有时间较长, 就会浪费 CPU 资源.

  1. synchronized 是可重入锁么?

是可重入锁.
可重入锁指的就是连续两次加锁不会导致死锁.
实现的方式是在锁中记录该锁持有的线程身份, 以及一个计数器(记录加锁次数). 如果发现当前加锁的线程就是持有锁的线程, 则直接计数自增.

到这里本篇文章就结束了
如果有帮助的话请一键三连~
小狗会请你喝饮料的
在这里插入图片描述
在这里插入图片描述

相关文章:

Java Web 实战 11 - 多线程进阶之常见的锁策略

常见的锁策略常见的锁策略1. 乐观锁 VS 悲观锁2. 普通的互斥锁 VS 读写锁3. 重量级锁 VS 轻量级锁4. 自旋锁 VS 挂起等待锁5. 公平锁 VS 非公平锁6. 可重入锁 vs 不可重入锁7. 常见面试题大家好 , 这篇文章给大家带来的是多线程中常见的锁策略 , 我们会给大家讲解 6 种类别的锁…...

(20)目标检测算法之YOLOv5计算预选框、详解anchor计算

目标检测算法之YOLOv5计算预选框、详解anchor计算 单节段目标检测算法中:预选框的设定直接影响最终的检测精度众所周知,yolov5中采用自适应调整预选框anchor的大小,但万事开头难,配置文件config中的预设还是很重要yolo算法作为on…...

3-1 SpringCloud快速开发入门: Ribbon 是什么

接上一章节Eureka 服务注册中心自我保护机制,这里讲讲Ribbon 是什么 Ribbon 是什么 通常说的负载均衡是指将一个请求均匀地分摊到不同的节点单元上执行,负载均和分为硬件负载均衡和软件负载均衡: **硬件负载均衡:**比如 F5、深信…...

Java【lambda表达式】语法及使用方式介绍

相关文章目录 第一篇: Java【EE初阶】进程相关知识 进程管理 内存管理 文章目录相关文章目录前言一、lambda表达式 是什么?1, lambda表达式 的背景2, 什么是 函数式接口3, lambda表达式 的语法二、lambda表达式 的使用方式1, 无参无返回值2, 有一个参…...

【AcWing】蓝桥杯备赛-深度优先搜索-dfs(2)

目录 写在前面: 题目:94. 递归实现排列型枚举 - AcWing题库 读题: 输入格式: 输出格式: 数据范围: 输入样例: 输出样例: 解题思路: 代码: AC &…...

‘conda‘不是内部或外部命令,也不是可运行的程序或批处理文件。

Anaconda环境搭建常见问题 conda不是内部或外部命令,也不是可运行的程序或批处理文件。 解决方案:配置环境变量 1.找到Anaconda Nvaigator单机右键 2.更多 3.打开文件所在位置 4.继续Anaconda Nvaigator单机右键,更多,选择文件…...

HTTP 3.0来了,UDP取代TCP成为基础协议,TCP究竟输在哪里?

TCP 是 Internet 上使用和部署最广泛的协议之一,多年来一直被视为网络基石,随着HTTP/3正式被标准化,QUIC协议成功“上位”,UDP“取代”TCP成为基础协议,TCP究竟“输”在哪里? HTTP/3 采用了谷歌多年探索的基…...

《JavaCV从入门到实战教程合集》介绍和目录

前言 《JavaCV从入门到实战教程合集》是2016年《JavaCV开发实战教程》和2018年《JavaCV入门教程》2022年《JavaCV音视频实战宝典》三合一汇总合集,完整包含JavaCV入门教程》、《JavaCV开发实战教程》系列和《JavaCV音视频实战宝典》系列所有付费内容。 《JavaCV入…...

Form Generator扩展 文本 组件

一、form-generator是什么?✨ ⭐️ 🌟 form-generator的作者是这样介绍的:Element UI表单设计及代码生成器,可将生成的代码直接运行在基于Element的vue项目中;也可导出JSON表单,使用配套的解析器将JSON解析成真实的表单。 但目前它提供的组件并不能满足我们在项目中的…...

【C/C++】必知必会知识点大总结

✍个人博客:https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 📚专栏地址:C/C知识点 📣专栏定位:整理一下 C 相关的知识点,供大家学习参考~ ❤️如果有收获的话,欢迎点赞👍…...

【JavaScript 逆向】百度旋转验证码逆向分析

声明本文章中所有内容仅供学习交流,相关链接做了脱敏处理,若有侵权,请联系我立即删除!案例目标爱企查百度安全验证百度搜索:aHR0cHM6Ly93YXBwYXNzLmJhaWR1LmNvbS9zdGF0aWMvY2FwdGNoYS8以上均做了脱敏处理,B…...

PCL 点云投影到直线(C++详细过程版)

目录 一、算法原理二、代码实现三、结果展示1、原始点云2、投影结果一、算法原理 直线方程有三种表示法:一般式、点向式、参数式。PCL中统一采用的是点向式,直线的点向式方程为: x − x 0 m = y −...

中缀表达式转后缀表示式,及后缀表达式的运算规则

后缀表达式又称为逆波兰表达式 一,中缀表达式如何转后缀表达式 假定给出以下中缀表达式 132*2-1; 要将该表达式转为后缀表达式,我们要按照一定的规则去走,并且用到栈。 先来看规则中缀转后缀的规则: 前提&#x…...

【C++】STL简介

文章目录什么是STLSTL版本 原始版本(HP版本) P.J.版本 RW版本 SGI版本STL六大组件 容器 算法 仿函数 空间配置器 迭代器 配接器STL缺陷什么是STL STL(standard template libaray-标准模板库):是C标准库的重要组成部分,不…...

(小甲鱼python)文件永久存储(上)总结 python文件永久存储(创建打开文件、文件对象的各种方法及含义)

一、文件永久存储 如何将数据永久的存放在硬盘上,具体如下。 1.打开文件 定义:往大了讲计算机系统中由操作系统管理的具有名称的存储区域,往小了讲是生活中的PPT、Excel、word三剑客、视频文件、音频文件等。 创建打开文件: open…...

甲酸溶液除钠离子,丙酸溶液除钾离子,医药液体除钾

水是医药行业中用量大、使用 泛的一种原料,它在生产过程中和药剂药品的制备中发挥着极其重要的作用。制药用水的原水通常为自来水或深井水,原水不能直接用作制剂用水或实验用水。因为原水中含有各类盐类和化合物,溶有CO2,还存在大…...

操作系统(2.2)--进程的描述与控制

目录 二、进程的描述 1.进程的定义和特征 1.1进程的定义 1.2进程的特征 2.进程的基本状态及转换 2.1进程的三种基本状态 2.2 三种基本状态的转换 2.3创建状态和中止状态 3.挂起操作和进程状态的转换 3.1 挂起状态的引入 3.2 引入挂起操作后三个进程状态的转换 …...

Python连接es笔记四之创建和删除操作

这一篇笔记介绍一下索引和数据的创建和删除。 其实对于索引来说,如果可以接触到 kibana 的话,可以很方便的在界面进行操作,这里简单介绍一下如何使用代码来操作索引的创建和删除。 索引的创建和删除操作 使用的还是 es 的连接:…...

字符串填充到指定长度

一、需求 在传输一个文件的时候,传输的是二进制数据,整个数据文件的结构为: 文件名称 文件本身 其中文件名称固定占30个byte,存在的情况就是,有的文件名比较长,有的文件名比较短,所有要补足30…...

macOS虚拟机安装全过程(VMware)

作为一名忠实果粉,我最大的愿望就是能够拥有一台Macbook,体验macOS,但是作为学生党,这价钱,贵到离谱啊~~~ 不过,VMware这个神器,可以解决一切问题:既然macOS可以在Macbook上运行&…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

【JVM】- 内存结构

引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...