【多线程】常见的锁策略 | 乐观锁 | 轻量级锁 | 重量级锁 | 自旋锁 | 挂起等待锁 | 读写锁 | 可重入锁 | 公平锁

news2024/9/20 2:39:19

文章目录

    • 一、常见的锁策略
      • 1.乐观锁 和 悲观锁(预测锁冲突的概率)
      • 2.轻量级锁 和 重量级锁 (实际消耗的开销)
      • 3.自旋锁 和 挂起等待锁
          • 自旋锁(Spin Lock)
          • 挂起等待锁
      • 4.读写锁
          • 标准库中读写锁的实现
      • 5.可重入锁 和 不可重入锁
      • 6.公平锁 和 非公平锁


一、常见的锁策略

1.乐观锁 和 悲观锁(预测锁冲突的概率)

​ 1.乐观锁和悲观锁都是泛指的概念。是“锁的一种特性”,是一类锁,而不是具体的锁。

悲观乐观,是根据对后续锁冲突是否激烈(频发)给出的预测。

  • 如果预测接下来锁冲突的概率不大,就可以少做一些工作,就称为“乐观锁”。

乐观锁认为多个线程访问同一个共享变量冲突的概率不大. 并不会真的加锁, 而是直接尝试访问数

据. 在访问的同时识别当前的数据是否出现访问冲突.

  • 如果预测接下来锁冲突的概率很大,就应该多做一些工作,就称为”悲观锁“。

悲观锁总是假设最坏的情况,每次去拿数据的时候,都认为别人会修改。所以在每次拿到数据时都会上锁,这样其他线程想拿这个数据的时候,就会发生阻塞。

​ 2.乐观锁的一个重要功能就是检查出数据是否发生了访问冲突。可以引入“版本号”来解决。

​ 3.Synchronized 初始使用乐观锁策略,当发现锁竞争比较频繁的时候, 就会自动切换成悲观锁策略


2.轻量级锁 和 重量级锁 (实际消耗的开销)

  • 锁的核心特点是“原子性”,由于CPU提供了“原子操作指令”,操作系统基于CPU的原子指令,实现了mutex互斥锁。JVM基于操作系统提供的互斥锁,实现了synchronized和ReentrantLock等关键字和类

​ 轻量级锁是指,锁的开销比较小,消耗的资源少。乐观锁通常是轻量级锁,可能存在特例,不绝对。

加锁机制尽可能不适用mutex,尽量使用用户态。少量的内核态用户态切换,不容易引发线程调度。

​ 重量级锁是指,锁的开销比较大,消耗的资源多。悲观锁通过是重量级锁。

加锁机制严重依赖mutex,存在大量的用户态内核态切换,容易引发线程的调度。

synchronized 开始是一个轻量级锁. 如果锁冲突比较严重, 就会变成重量级锁


3.自旋锁 和 挂起等待锁

自旋锁(Spin Lock)

​ 就属于一种轻量级锁的典型实现。往往在纯用户态实现,比如使用了一个While循环,不停的检查当前锁是否被释放。如果没被释放就继续进行循环,释放了就获取到锁,从而结束循环。不涉及到内核和阻塞,属于’‘忙等’'。相当于消耗CPU来换取更快的响应速度。

挂起等待锁

​ 就属于一种重量级锁的典型实现。要借助系统api来实现,一旦出现锁竞争,就会在内核中触发一系列动作(比如让这个线程进入阻塞状态,暂时不参与CPU的调度。阻塞的开销是比较大的)

4.读写锁

读写锁,就是把“读”和“写”两种操作区别开来:

1.读加锁 :读的时候,能读,但是不能写。

2.写加锁 :写的时候,不能读,也不能写。

​ 读锁和读锁之间,不会产生竞争(多线程读取同一个数据,没有线程安全问题)。读锁和写锁有竞争。写锁和写锁也有竞争。在实际的开发中,往往是“读多写少”。使用读写锁,就可以优化“读多写少”这样的场景。

标准库中读写锁的实现
  • ReentrantReadWriteLock.ReadLock 类表示一个读锁. 这个对象提供了 lock / unlock 方法进行加锁解锁.

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

要进行区别:在数据库,事务的隔离性中涉及到:

1.解决脏读 :写加锁(我写的时候,别人不能去读)

2.解决不可重复读 :读加锁:(你读的时候,我也不能写)

3.解决幻读 :串行化

数据库写加锁:写的时候不能读

数据库读加锁:读的时候不能写(是简化版本的模型)

  • synchronized不是读写锁。

5.可重入锁 和 不可重入锁

一个线程对同一把锁,连续加锁两次,不会死锁,就是可重入锁。会死锁,就是不可重入锁。

可重入锁,锁里面保存了当前是哪个线程加上的锁,同时维护了一个计数器,所以第二次加锁的时候,不会触发阻塞等待,而是自增计数器。后续解锁时再进行自减。直到计数器等于0时,才会真正释放锁。

6.公平锁 和 非公平锁

  • 这里的公平,指的是,对排队等待的线程公平,而不是值人人平等~

​ 当很多线程去尝试加一把锁的时候,一个线程拿到锁,其他线程就会阻塞等待。当第一个线程释放锁时:

公平锁:剩下的线程 按照“先来后到"的顺序,来拿到锁。

非公平锁:剩下的线程以“均等”的概率,重新竞争锁。

操作系统提供的加锁API,默认情况下,就属于非公平锁。

要想实现 公平锁 ,需要引入额外的队列,来维护这些线程的加锁顺序。

点击移步博客主页,欢迎光临~

偷cyk的图

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

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

相关文章

大话设计模式-依赖倒转原则

依赖倒转原则 在大话设计模式这本书中,作者通过电话修电脑这个例子引入了面向对象设计的基本原则之一:依赖倒转原则。 概念 依赖倒转原则是面向对象设计的基本原则之一,它用于减少类之间的耦合,提高系统的灵活性和可维护性。在…

基于stm32的UART高效接收DMA+IDLE编程示例

目录 基于stm32的UART高效接收DMAIDLE编程示例实验目的场景使用原理图UART的三种编程方式IDLE程序设计串口配置配置中断配置DMA代码片段本文中使用的测试工程 基于stm32的UART高效接收DMAIDLE编程示例 本文目标:基于stm32_h5的freertos编程示例 按照本文的描述&am…

Linux服务器运维工具箱 监控管理建站一个脚本全搞定!

Linux服务器运维工具箱 监控管理建站一个脚本全搞定! 一款全能脚本工具箱,使用shell脚本编写。专为Linux服务器监控、测试和管理而设计。无论您是初学者还是经验丰富的用户,该工具都能为您提供便捷的解决方案。集成了独创的Docker管理功能&a…

智慧社区整体解决方案(PPT)

1、背景与现状分析 2、解决方案 3、功能及应用场景介绍 软件资料清单列表部分文档: 工作安排任务书,可行性分析报告,立项申请审批表,产品需求规格说明书,需求调研计划,用户需求调查单,用户需求…

YOLOv9改进策略 | Conv篇 | 利用YOLO-MS的MSBlock二次创新RepNCSPELAN4(全网独家创新)

一、本文介绍 本文给大家带来的改进机制是利用YOLO-MS提出的一种针对于实时目标检测的MSBlock模块(其其实不能算是Conv但是其应该是一整个模块),我们将其用于RepNCSPELAN中组合出一种新的结构,来替换我们网络中的模块可以达到一种轻量化的作用&#xff…

Flutter MQTT通信(实现聊天功能)

MQTT协议简介: MQTT(Message Queuing Telemetry Transport)是一种轻量级的、开放的、基于发布/订阅模式的消息传输协议,最初由IBM开发。它专门设计用于在低带宽、不稳定的网络环境下进行高效的消息传输。 学习完本篇文章&#x…

ESP32嵌入式物联网开发实战笔记-C编程基础知识点【doc.yotill.com】

乐鑫ESP32入门到精通项目开发参考百例下载: 链接:百度网盘 请输入提取码 5.1 C 语言基础知识复习 本节我们给大家介绍一下 C 语言基础知识,对于 C 语言比较熟练的开发者,可以跳过此节,对于基础比较薄弱的开发者&…

HCF-Net:用于红外小目标检测的分层上下文融合网络

摘要 红外小目标检测是一项重要的计算机视觉任务,涉及在红外图像中识别和定位微小物体,这些物体通常仅包含几个像素。然而,由于物体尺寸极小以及红外图像中通常复杂的背景,这项任务面临困难。在本文中,我们提出了一种…

40.Vue 应用

Vue 应用 应用实例 每个 Vue 应用都是通过 createApp函数创建一个新的 应用实例 import { createApp } from vueconst app createApp({/* 根组件选项 */ })根组件 我们传入 createApp 的对象实际上是一个组件,每个应用都需要一个“根组件”,其他组件…

HarmonyOS NEXT 使用XComponent + Vsync 实现自定义动画

介绍 XComponent 提供了应用在 native 侧调用 OpenGLES 图形接口的能力,本文主要介绍如何配合 Vsync 事件,完成自定义动画。在这种实现方式下,自定义动画的绘制不在 UI 主线程中完成,即使主线程卡顿,动画效果也不会受…

【Camera Sensor Driver笔记】二、点亮指南之Sensor Module XML

Camera Sensor module XML详解: cameraId 与 slot id 一一对应 (即:dtsi中相对应的sensor的 cell-index ) moduleName 模组厂名称 sensorName sensor 名称 actuatorName 马达名称 oisName …

Xavier 初始化

Xavier 初始化 为什么在 W [ l ] n p . r a n d o m . r a n d n ( s h a p e ) n p . s q r t ( 1 n [ l − 1 ] ) W^{[l]}np.random.randn(shape)\times np.sqrt(\frac{1}{n^{[l-1]}}) W[l]np.random.randn(shape)np.sqrt(n[l−1]1​) 中需要乘以 n p . s q r t ( 1 n […

宽带上网技术发展(xDSL、PON)

文章目录 xDSL(x数字用户线,x Digital Subscriber Line)IDSL(基于ISDN数字用户线路)ADSL(不对称数字用户线路)RADSL(速率自适应数字用户线路)HDSL(高速率数字用户线路)VDSL(极高速率数字用户线路)SDSL(单对线路/对称数字用户线路) PON&#x…

Linux驱动开发——(三)并发与竞争

目录 一、并发与竞争简介 二、原子操作 2.1 原子操作简介 2.2 原子整形操作API 2.3 原子位操作API 2.4 原子操作驱动代码 三、自旋锁 3.1 自旋锁简介 3.2 自旋锁API 3.3 自旋锁驱动代码 四、信号量 4.1 信号量简介 4.2 信号量API 4.3 信号量驱动代码 一、并发与…

SpringCloud系列(4)--SpringCloud微服务工程构建

前言:在上节我们新建了一个SpringCloud父工程,这一节主要是构建微服务工程,通过实现订单模块和支付模块来熟悉微服务的概念和构建过程。 1、在父工程下新建模块 2、选择模块的项目类型为Maven并选择模块要使用的JDK版本 3、填写子模块的名称&…

算法|最大堆、最小堆和堆排序的实现(JavaScript)

一些概念 堆&#xff1a;特殊的完全二叉树&#xff0c;具有特定性质的完全二叉树。大根堆&#xff1a;父节点 > 子节点小根堆&#xff1a;父节点 < 子节点 二叉堆也属于完全二叉树&#xff0c;所以可以用数组表示。 若下标从1开始&#xff0c;左节点为 2*i &#xff0…

Java的Future机制详解

Java的Future机制详解 一、为什么出现Future机制二、Future的相关类图2.1 Future 接口2.2 FutureTask 类 三、FutureTask的使用方法四、FutureTask源码分析4.1 state字段4.2 其他变量4.4 构造函数4.5 run方法及其他 一、为什么出现Future机制 常见的两种创建线程的方式。一种是…

高架学习笔记之软件架构风格

目录 零、什么是软件架构风格 一、常见的软件架构风格 二、数据流风格 2.1. 批处理风格 2.2. 管道-过滤器风格 三、调用/返回风格 3.1. 主/子程序风格 3.2. 面向对象风格 3.3. 层次型风格 3.4. 客户端/服务器风格 3.4.1. 两层C/S体系结构 3.4.2. 三层C/S体系结构 …

MBD_入门篇_20_Simulink子系统

20.Simulink子系统 20.1 概述 Simulink的子系统&#xff0c;相当于代码的function函数&#xff0c;但是模型的子系统又不完全等效于代码的函数。虚拟子系统并不会生成函数&#xff0c;而是以代码块的形式放在相应的调用位置上。模型层面我们使用子系统去做模块化的设计&#xf…

Mini-Gemini: 探索多模态视觉语言模型的新境界

一、背景 在数字化时代&#xff0c;人工智能的发展正以前所未有的速度推进。特别是在多模态学习领域&#xff0c;结合视觉和语言的能力已成为研究的热点。最近&#xff0c;一篇名为“Mini-Gemini: Mining the Potential of Multi-modality Vision Language Models”的文章在arX…