常见实用的锁策略详解

news2024/11/19 0:33:38

🎈专栏链接:多线程相关知识详解           

目录

1.乐观锁VS悲观锁

2.读写锁VS普通互斥锁

3.轻量级锁VS重量级锁

4.自旋锁VS挂起等待锁 

5. 公平锁VS非公平锁

6.可重入锁VS不可重入锁

7.关于synchronized的锁策略以及自适应


1.乐观锁VS悲观锁

乐观锁:预测锁冲突的概率不高,因此做的工作就可以简单点

悲观锁:预测锁冲突的概率较高,因此做的工作就要复杂一些

锁冲突就是多个线程竞争同一把锁,会产生阻塞等待

举个例子:

乐观锁:A在学校的教室内卷的时候,就比较乐观,就觉得在教室学习的时候,不怕被B发现自己在偷偷内卷,而且B来教室内卷的概率比较少,就不关教室门,即使B进来发现A自己在内卷,也不影响A自己学习

悲观锁:B在教室内卷的时候,就比较悲观,觉得A天天想要学习,来教室内卷,怕A的成绩超过B自己,就每次都关教室门,即使A不来教室学习,也把门给关上,多做了一步锁门操作

 这两种锁是站在加锁解锁的角度看待的,看的是加锁解锁的过程中所干的活是多还是少

2.读写锁VS普通互斥锁

读写锁:

        Ⅰ:加读锁

        Ⅱ:加写锁

读锁和读锁之间不会产生竞争

写锁和写锁之间会产生竞争

读锁和写锁会产生竞争

普通互斥锁:就如同Synchronized,当两个线程竞争同一把锁的时候就会产生阻塞等待

多个线程同时读一个变量并没有问题,而且读的场景相比于写的场景就多了很多,使用读写锁相比于普通互斥锁就减少了很多的锁竞争,大大的优化了效率

 3.轻量级锁VS重量级锁

轻量级锁的加锁解锁开销比较少,典型的是纯用户态的加锁解锁逻辑,开销是比较少的

重量级锁的加锁解锁开销比较大,典型的是进入了系统内核态的加锁解锁逻辑,开销是比较大的

这两种锁是站在结果的角度看待最终加锁解锁消耗的时间是多还是少,和乐观锁与悲观锁并不一样

通常情况下乐观锁比较轻量,悲观锁比较重量,但是也并不绝对

4.自旋锁VS挂起等待锁 

自旋锁:相当于是"忙等"的状态,大量消耗的CPU资源,反复询问当前锁是否就绪

挂起等待锁:先把CPU资源空闲出来去做其他的事情,过一段时间才询问当前锁是否就绪

举个例子:

在我们等人的时候,对方还没有到约定地点,一直反复的打电话催促就是自旋锁,而当你发现对方还没到的时候,就在约定的地点找个地方玩手机,叫他来了再在约定的地点旁边找我们一下,多消耗一点时间,却能够用这些时间去做其他的事情,时间被利用起来了,这就是挂起等待锁

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

5. 公平锁VS非公平锁

公平锁:公平锁是先来后到,谁先来谁就拿到锁

非公平锁:多个线程同时竞争一把锁,有一个线程是比较晚来的,却比其他先来的线程先拿到锁

举个例子:

t1,t2,t3三个线程竞争同一把锁,t1先来的,所以t1先拿到了锁,这就叫公平锁.

而如果t3是晚来的,然后t3比其他两个线程先拿到了锁,这就叫非公平锁

操作系统默认的锁的调度,是非公平的情况

想要实现一个公平锁,就需要引入额外的数据结构,来记录线程加锁的顺序,需要一定的额外开销

6.可重入锁VS不可重入锁

可重入锁:同一个线程对同一把锁连续加锁两次不会造成死锁

不可重入锁:同一个线程对同一把锁连续加锁两次会造成死锁

举个例子:

有一次A去上教室学习把门给锁上了,后面要出去的时候突然想从窗户翻出去不走大门,过了一会A忘记了这件事情,等A回来教室的时候发现教室里面门锁着,就觉得里面有人,但实际上并没有人.然后A在这里敲门等里面的人过来开门,但却是永远也等不到里面有人来给A开门,A就会一直等下去,这就是死锁

 

针对这个代码,第一次能够加锁成功,而第二次加锁的时候就会加锁失败,因为锁已经被占用,就会在第二次加锁这里进行阻塞等待,等到第一把锁被解锁,第二次加锁才会成功.而第一把锁解锁成功的条件是要求执行完synchronized代码块,也就是要求第二把锁加锁成功

public class Demo3 {
    static class Counter{
        public synchronized void increase() {//加锁
            increase2();
        }

        public void increase2(){
            increase3();
        }

        public void increase3(){
            increase4();
        }

        public synchronized void increase4(){//加锁

        }
    }
    public static void main(String[] args) {
    
    }
}

上面这个代码就很有可能会一不小心就写出来,因为调用了多个方法并不能直观的看出来,就会造成死锁

因此更好的做法是不要让上述情况死锁

针对上述情况,不会产生死锁的话,这样的锁就叫做可重入锁,反而就叫不可重入锁

synchronized是可重入锁

可重入锁的实现要点:

Ⅰ.让锁里持有线程对象,记录是谁加了锁

Ⅱ.维护一个计数器,用来衡量啥时候是真加锁,啥时候是真解锁,啥时候是直接放行

引入一个计数器,每次加锁的时候计数器就++,每次解锁的时候计数器就--,如果计数器为0,此时的加锁才是真加锁,同样计数器为0,此时的解锁才是真解锁

如果程序抛出了异常,没有人catch就脱离了之前的代码块,脱离了一层代码,计数器就-1,脱离到计数器为0,也就解锁了,同理加锁代码中出现异常,也是不会死锁的,因为Java使用关键字结合代码块来做解锁操作,无论如何解锁代码都能执行到的

7.关于synchronized的锁策略以及自适应

①既是乐观锁,也是悲观锁

②既是轻量级锁,也是重量级锁

③既是自旋锁,也是挂起等待锁

④不是读写锁,是普通互斥锁

⑤是非公平锁

⑥是可重入锁

synchronized是自适应的,初始使用的时候,是 乐观锁/轻量级锁/自旋锁,如果竞争不激烈则保持这个状态不变,如果锁竞争激烈了,synchronized会自动升级成为 悲观锁/重量级锁/挂起等待锁,所以synchronized是"智能"的

                    

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

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

相关文章

Windows中安装配置RabbitMQ

本次安装环境win10,采用版本 OTP 25.0.3https://github.com/erlang/otp/releases/tag/OTP-25.0.3RabbitMQ 3.10.13 Release RabbitMQ 3.10.13 rabbitmq/rabbitmq-server GitHubOpen source RabbitMQ: core server and tier 1 (built-in) plugins - Release Rabbi…

[N1CTF 2018]eating_cms parse_url绕过

index.php <?php require_once "function.php"; if(isset($_SESSION[login] )){Header("Location: user.php?pageinfo"); } else{include "templates/index.html"; } ?> function.php <?php session_start(); require_once &q…

Kafka Producer 自定义 拦截器 序列化

Kafka Producer 拦截器 & 序列化 前言 文章中的版本信息、maven依赖如下 JDK17 kafka_2.13-3.3.1 pom文件 <dependencies><dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId><version>…

NR HARQ (四)Type-2 HARQ-ACK codebook

微信同步更新欢迎关注同名modem协议笔记 上篇提到type-1 HARQ-ACK codebook&#xff0c;即semi-static codebook&#xff0c;UE要为每个PDSCH候选位置生成反馈&#xff0c;也会包含实际没有下行传输的PDSCH&#xff0c;再加上配置CBG的场景&#xff0c;HARQ-ACK 码本中包含的无…

【Linux 内核 内存管理】物理内存组织结构

一、 UMA和NUMA两种模型 共享存储型多处理机有两种模型 一致内存访问&#xff08;Uniform-Memory-Access&#xff0c;简称UMA&#xff09;模型 非一致内存访问&#xff08;Nonuniform-Memory-Access&#xff0c;简称NUMA&#xff09;模型 UMA模型 物理存储器被所有处理器件均…

超标量处理器设计——第八章_发射

超标量处理器设计——第八章_发射 参考《超标量处理器》姚永斌著 文章目录超标量处理器设计——第八章_发射8.1 简述8.1.1 集中式 VS. 分布式8.1.2 数据捕捉 VS. 非数据捕捉8.1.3 压缩 VS. 非压缩8.2 发射过程的流水线8.2.1 非数据捕捉结构的流水线8.2.2 数据捕捉结构的流水线8…

随手写系列——写一个凯撒密码转换页面

文章目录先展示效果H5编写C3编写JS编写——方法一&#xff1a;过程版JS编写——方法二&#xff1a;对象版代码获取先展示效果 &#xff08;因为主要是实现功能&#xff0c;所以CSS写的很粗糙&#xff09; H5编写 基础结构如下&#xff1a; 先构成最外面的大盒子.box&#…

【Flutter】之便于提高开发效率的周边库和轮子

GetX 状态管理 GetX包含很多功能&#xff0c;各种弹出widget、路由管理、国际化、Utils、状态管理等。 基于路由管理 1. 添加到项目中 1.1. 将此添加到pubspec.yaml文件中。 get: 4.1.4 1.2. 在命令行中运行 flutter packages get 1.3. 在MaterialApp前面加上 “Get”&…

centos7 yum安装postgreSQL

安装环境centos7.6 安装步骤&#xff1a; 1、安装postgresql&#xff1a; yum install postgresql-server 2、安装postgresql 扩展包&#xff1a; yum install postgresql-contrib 3、初始化&#xff1a; postgresql-setup initdb 4、启动开机自启动&#xff1a; systemc…

说话人识别神经网络推理方式

概述 说话人识别是一个序列总结&#xff08;Sequence Summarization&#xff09;任务&#xff0c;输入是音频&#xff08;或者说&#xff0c;声学特征的序列&#xff09;&#xff0c;输出是说话人的嵌入码&#xff0c;有的神经网络可以输入一对音频&#xff0c;直接输出这对音…

java微信支付v3系列——9.微信支付之商家转账API

这个功能就比较复杂了&#xff0c;首先是得有90天的资金流水才能开通&#xff0c;其次开通后还需要在官网进行配置&#xff0c;不能直接调用&#xff0c;并且限制了IP地址。 如下图所示&#xff0c;首先需要进行产品设置&#xff0c;将里面都设置好后才能进行开发&#xff0c;…

feign 调用常见问题避坑指南!

摘要&#xff1a;主要是总结了一下这段时间在使用 feign 的过程中的遇到的一些坑点。一、Get请求自动转化成POST的问题1、client 请求参数没有加上 RequestParam 注解问题代码&#xff1a;GetMapping("/showName") String showName(String name);错误提示&#xff1a…

让 APISpace 告诉你什么场景使用什么API

Q1&#xff1a;某商家打算搞年底促销活动&#xff0c;需要将活动信息通过短信的形式通知给用户&#xff0c;这个场景可以用什么接口&#xff1f; 发送通知类的短信&#xff0c;可以使用 通知短信 API~ 通知短信&#xff0c;支持三大运营商&#xff0c;虚拟运营商短信发送&…

第14章 并发控制与恢复

第14章 并发控制与恢复 考试范围&#xff1a; 14.1-14.3, 14.8-14.11 考试题型&#xff1a; 事务操作 考试内容&#xff1a; 1、锁/共享锁/排它锁的概念 2、多粒度锁 Multiple Granularity 3、两阶段封锁协议 The Two-Phase Locking Protocol 两段锁协议是指同一事务对任何…

2.前端笔记-JS-JS3种书写位置、注释、输入输出

书写位置 行内式嵌入式外部文件引入 1、行内式JS 可以将单行或少量的JS代码写在HTML标签的事件属性中&#xff08;以on开头的属性&#xff09;&#xff0c;如onclick单双引号使用&#xff1a;HTML中推荐双引号&#xff0c;JS中推荐单引号&#xff0c;如 <input type&quo…

vue实现将自己网站(h5链接)分享到微信中形成小卡片(超详细)

大家好&#xff0c;我是雄雄。 前言 我们在分享公众号信息到微信或者群中的时候&#xff0c;会出现一个小卡片&#xff0c;如下所示&#xff1a; 但是呢&#xff0c;这种小卡片只能走微信的接口来实现&#xff0c;比如我们从公众号、小程序中分享的内容可以是这样的。如果我们…

0基础转行,四个月,改变了我的人生!

转行对于很多人而言都是一个新的开始&#xff0c;但有的人是决定了立马去做&#xff0c;而有的人则是犹犹豫豫&#xff0c;我考虑考虑吧、还没有决定好、过段时间再说吧…… 就这样&#xff0c;相似情况的两个人&#xff0c;最后有了不同的结果。 很多人总是以我很忙、学历不高…

自学100天,零基础转行软件测试,我要以更好的姿态奔赴下一场山海!

三年大专一场空 专业是电子商务&#xff0c;18年毕业&#xff0c;当时在报考时时觉得电子商务挺高大上的&#xff0c;觉得电商肯定会有前途&#xff0c;以后毕业肯定好找工作&#xff0c;跟大多数人一样&#xff0c;我开始幻想我以后毕业以后的纸醉金迷的生活&#xff0c;我以…

模数转换器ADC

模数转换器ADC F28335内部的ADC模块是一个12位分辨率的、具有流水线结构的模数转换器,其结构框图如图11-1所示。从图11-1可以看到,F28335的ADC模块一共具有16个采样通道,分成了两组,一组为ADCINAO~ ADCINA7,另一组为ADCINBO~ADCINB7。A组的通道使用采样保持器A,也就是图…

【SCI论文解读复现NO.1】基于Transformer-YOLOv5的侧扫声纳图像水下海洋目标实时检测

前言 此前出了目标改进算法专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读最新目标检测算法论文&#xff0…