【Java EE 初阶】锁策略以及CAS问题

news2024/9/23 7:28:29

目录

1.常见的锁策略

1.乐观锁 vs 悲观锁

2.读写锁

3.重量级锁 vs 轻量级锁

4.自旋锁(Spin Lock)

5.公平锁 vs 非公平锁

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

7.Synchronized实现了哪些锁策略?

1.是乐观锁也是悲观锁

2.既是轻量级锁也是重量级锁

3.是普通互斥锁

4.是非公平锁

5.是可重入锁

6.既是自旋锁也是挂起等待锁

8.CAS(Compare And Swap)

9.基于CAS的应用,原子类

 10.CAS实现自旋锁

11.CAS的ABA问题

1.ABA问题

2.解决ABA问题

12.加锁工作过程

13.锁消除

14.锁粗化


1.常见的锁策略

1.乐观锁 vs 悲观锁

  • 悲观锁: 一开始就会上锁
  • 乐观锁: 假设数据一般情况下不会产生并发冲突,所以在数据进行提交更新的时候,才会正式对数据是否产生并发冲突进行检测,如果发现并发冲突了,则让返回用户错误的信息,让用户决定如何去做

2.读写锁

  • 多线程之间,数据的读取方之间不会产生线程安全问题,但数据的写入方互相之间以及和读者之间都需 要进行互斥。如果两种场景下都用同一个锁,就会产生极大的性能损耗。所以读写锁因此而产生。
  • 读写锁(readers-writer lock),看英文可以顾名思义,在执行加锁操作时需要额外表明读写意图,复数读者之间并不互斥,而写者则要求与任何人互斥。

读写锁就是把读操作和写操作区分对待. Java 标准库提供了 ReentrantReadWriteLock , 实现了读写锁.
  • ReentrantReadWriteLock.ReadLock 类表示一个读锁. 这个对象提供了 lock / unlock 方法进行加锁解锁.
  • ReentrantReadWriteLock.WriteLock 类表示一个写锁. 这个对象也提供了 lock / unlock 方法进行加锁解锁.
其中,
  • 读加锁和读加锁之间, 不互斥.
  • 写加锁和写加锁之间, 互斥.
  • 读加锁和写加锁之间, 互斥.
注意, 只要是涉及到 "互斥", 就会产生线程的挂起等待. 一旦线程挂起, 再次被唤醒就不知道隔了多
久了. 因此尽可能减少 "互斥" 的机会, 就是提高效率的重要途径
读写锁特别适合于 "频繁读, 不频繁写" 的场景

3.重量级锁 vs 轻量级锁

锁的核心特性 "原子性", 这样的机制追根溯源是 CPU 这样的硬件设备提供的.
  • CPU 提供了 "原子操作指令".
  • 操作系统基于 CPU 的原子指令, 实现了 mutex 互斥锁.
  • JVM 基于操作系统提供的互斥锁, 实现了 synchronized ReentrantLock 等关键字和类.
重量级锁: 加锁机制重度依赖了 OS 提供了 mutex
  • 大量的内核态用户态切换
  • 很容易引发线程的调度

重量级锁过程

  • 执行加锁操作, 先进入内核态.
  • 在内核态判定当前锁是否已经被占用
  • 如果该锁没有占用, 则加锁成功, 并切换回用户态.
  • 如果该锁被占用, 则加锁失败. 此时线程进入锁的等待队列, 挂起. 等待被操作系统唤醒.
  • 经历了一系列的沧海桑田, 这个锁被其他线程释放了, 操作系统也想起了这个挂起的线程, 于是唤醒 这个线程, 尝试重新获取锁.
这两个操作, 成本比较高. 一旦涉及到用户态和内核态的切换, 就意味着 "沧海桑田".
轻量级锁: 加锁机制尽可能不使用 mutex, 而是尽量在用户态代码完成. 实在搞不定了, 再使用 mutex. .
  • 少量的内核态用户态切换.
  • 不太容易引发线程调度
此处的轻量级锁就是通过 CAS 来实现.
  • 通过 CAS 检查并更新一块内存 (比如 null => 该线程引用)
  • 如果更新成功, 则认为加锁成功
  • 如果更新失败, 则认为锁被占用, 继续自旋式的等待(并不放弃 CPU).
自旋操作是一直让 CPU 空转, 比较浪费 CPU 资源.
因此此处的自旋不会一直持续进行, 而是达到一定的时间/重试次数, 就不再自旋了.
也就是所谓的 "自适应"

4.自旋锁(Spin Lock

  • 如果获取锁失败, 立即再尝试获取锁, 无限循环, 直到获取到锁为止. 第一次获取锁失败, 第二次的尝试会在极短的时间内到来.
  • 自旋锁是一种典型的 轻量级锁 的实现方式.
  • 优点: 没有放弃 CPU, 不涉及线程阻塞和调度, 一旦锁被释放, 就能第一时间获取到锁.
  • 缺点: 如果锁被其他线程持有的时间比较久, 那么就会持续的消耗 CPU 资源. (而挂起等待的时候是不消耗 CPU ).

5.公平锁 vs 非公平锁

  • 公平锁: 遵守 "先来后到". B C 先来的. A 释放锁的之后, B 就能先于 C 获取到锁.
  • 非公平锁: 不遵守 "先来后到". B C 都有可能获取到锁.
  • 操作系统内部的线程调度就可以视为是随机的. 如果不做任何额外的限制, 锁就是非公平锁. 如果要 想实现公平锁, 就需要依赖额外的数据结构, 来记录线程们的先后顺序.
  • 公平锁和非公平锁没有好坏之分, 关键还是看适用场景.

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

可重入锁的字面意思是可以重新进入的锁,即允许同一个线程多次获取同一把锁
比如一个递归函数里有加锁操作,递归过程中这个锁会阻塞自己吗?如果不会,那么这个锁就是可重入 锁(因为这个原因可重入锁也叫做递归锁
  • Java里只要以Reentrant开头命名的锁都是可重入锁,而且JDK提供的所有现成的Lock实现类,包括
  • synchronized关键字锁都是可重入的。
  • Linux 系统提供的 mutex 是不可重入锁.

7.Synchronized实现了哪些锁策略?

1.是乐观锁也是悲观锁

开始没有线程竞争的时候无锁,当有第一个线程来使用的时候加偏向锁,偏向锁并不是真正的加锁,只是给对象头做一个偏向锁的标记,记录这个锁属于哪个线程,如果后续没有其他线程来争抢锁,那就不用真正的加锁,(避免了加锁解锁的系统开销)并记录当前线程的版本号,当出现两个以上的线程竞争时变为轻量级锁,当越来越多的线程参与到竞争中,自旋不能快速获取到锁状态,此时就会变为重量级锁

2.既是轻量级锁也是重量级锁

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

3.是普通互斥锁

4.是非公平锁

5.是可重入锁

6.既是自旋锁也是挂起等待锁

8.CAS(Compare And Swap)

当多个线程同时对某个资源进行CAS操作,只能有一个线程操作成功,但是并不会阻塞其他线程,其他线程只会收到操作失败的信号

9.基于CAS的应用,原子类

 两个线程通过CAS同时对一个共享变量做自增,通过不停的自旋检查预期值来保证了线程安全

while循环是在应用层执行的,也就是用户态锁比内核态的锁效率要高很多

Compare And Swap 是CPU中的一条指令,可以完成CAS的整个操作(比较并交换),简而言之,是因为硬件予以了支持,软件层面才能做到

 10.CAS实现自旋锁

11.CAS的ABA问题

1.ABA问题

在上述过程中,两个A校验的时候都可以通过,但两个A却并非同一个A,

如果CAS中出现ABA问题,在真实的业务中可能会造成比较大的影响

2.解决ABA问题

给预期值加一个版本号,在做CAS操作的同时更新预期值的版本号,版本号只增不减

CAS 操作在读取旧值的同时, 也要读取版本号真正修改的时候

  • 如果当前版本号和读到的版本号相同, 则修改数据, 并把版本号 + 1.
  • 如果当前版本号高于读到的版本号. 就操作失败(认为数据已经被修改过了)

12.加锁工作过程

JVM synchronized 锁分为 无锁、偏向锁、轻量级锁、重量级锁 状态。会根据情况,进行依次升级

13.锁消除

14.锁粗化

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

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

相关文章

K_A37_005 基于STM32等单片机驱动ADS1115 ADC模块 串口与OLED0.96双显示

K_A37_005 基于STM32等单片机驱动ADS1115 ADC模块 串口与OLED0.96双显示 所有资源导航一、资源说明二、基本参数参数引脚说明 三、驱动说明IIC时序对应程序: 四、部分代码说明1、接线引脚定义1.1、STC89C52RCADS1115 ADC模块1.2、STM32F103C8T6ADS1115 ADC模块 五、基础知识学习…

解决“未在本地计算机注册“OraOLEDB.Oracle.1”提供程序“问题

由于本地使用Oracle.ManagedDataAccess批量插入问题,连接数据库时报错 : ProviderOraOLEDB.Oracle;Data Sourceorcl;User IdQueueDp;PasswordQueueDp 此问题之前解决过没记录,又遇到了,忘了怎么解决,试了很多没效果 解决办法一、…

用好git stash,工作超nice

一、介绍 如果修改后的内容还不想commit,就可以用git stash命令。它会将工作区和暂存区中的修改(也就是还没commit的内容)都会被保存到堆栈里,并在之后恢复到任意指定的分支上。 二、应用场景 1、在分支a进行开发feature 1时,突然需要紧急…

2、Orangepi Zero2刷机和系统启动

目录 2.1 工具安装 2.2 刷机 2.3 登录系统 2.4 修改登陆密码 2.5 网络配置 2.6 SSH登陆开发板 就像买了电脑,出厂带有 windows 操作系统,才算是正在的电脑,开发板需要烧写对应的系统固件,才 能正常发挥作用 工具 Orangepi Zero2…

【异常解决】浏览器无法访问此网站ERR_UNSAFE_PORT/网页可能无法连接,或者它已永久性地移动到了新网址问题解决方案

浏览器无法访问此网站ERR_UNSAFE_PORT问题解决方案 一、问题描述二、问题原因三、解决方案3.1 方案1修改服务器访问端口号(推荐)3.2 方案2修改浏览器设置3.2.1 Chrome浏览器3.2.2 Firefox浏览器3.2.3 Edge浏览器 一、问题描述 访问某一个特定的网址之后…

Flume系列:Flume Channel使用

目录 Apache Hadoop生态-目录汇总-持续更新 1:Kafka Channel 2:File Channel 3:Memory Channel Apache Hadoop生态-目录汇总-持续更新 系统环境:centos7 Java环境:Java8 1:Kafka Channel Kafka Chan…

vim键位图+vim基本操作命令表

前言:本章末vim的基本操作命令总结的比较全,建议收藏起来,方便后面使用时作字典查找。 目录 一、什么是vi(vim)? vim键盘 二、vim工作模式 1)命令模式 2)编辑模式 3)末行模式 4&#xf…

「2024」预备研究生mem-等差数列基础

一、等差数列基础 二、课后练习题 思路,知道a1和d ,就可以知道an,sn

Kafka 集成 SpringBoot, 快速入门

一、kafka的生产者和消费者 1. 生产者发送消息的流程 2. 消费者接收消息的流程 二、 java 代码实现 1. 添加依赖&#xff1a; <dependency><groupId>org.apache.kafka</groupId><artifactId>kafka_2.12</artifactId></dependency>2. 实现…

回溯算法例题(剪枝策略)

目录 1.组合1.77. 组合2.216. 组合总和 III3.17. 电话号码的字母组合4.39. 组合总和5.40. 组合总和 II 2.分割1.131. 分割回文串2.*93. 复原 IP 地址 3.子集1.78. 子集2.90. 子集 II 4.排列1.46. 全排列2.47. 全排列 II 5.棋盘问题1.51. N 皇后2.37. 解数独 6.其他1.491. 递增子…

系统移植 5-10

1.进入linux内核源码目录下&#xff0c;打开Makefile文件&#xff0c;搜索vmlinux&#xff0c;找到cmd_link-vmlinux命令&#xff0c; 1179 cmd_link-vmlinux \ 1180 $(CONFIG_SHELL) $< "$(LD)" "…

不同应用场景瑞芯微RK3568主板方案定制

随着物联网和智能设备的迅猛发展&#xff0c;瑞芯微RK3568主板方案作为一种高性能的系统System-on-a-chip&#xff08;SoC&#xff09;&#xff0c;已经成为嵌入式系统、智能家居设备和工业自动化设备等应用场景的首选方案。定制瑞芯微RK3568主板方案可以满足不同应用场景的需求…

科技云报道:ChatGPT应用爆火,安全的大数据底座何处寻?

科技云报道原创。 毫无疑问&#xff0c;AIGC正在给人类社会带来一场深刻的变革。 而剥开其令人眼花缭乱的华丽外表&#xff0c;运行的核心离不开海量的数据支持。 ChatGPT的“入侵”已经引起了各行各业对内容抄袭的担忧&#xff0c;以及网络数据安全意识的提高。 虽然AI技术…

线程的原子性、可见性、有序性及线程安全知识整理

要想保证线程安全&#xff0c;必须同时满足原子性、可见性、有序性。 一、定义 1.1 原子性 一个操作或者多个操作&#xff0c;要么全部执行&#xff0c;并且执行的过程不会被打断&#xff0c; 要么就全部不执行&#xff08;一个操作是不可被分割的&#xff09;。 Java中实现…

JavaScript经典教程(七)-- JavaScript初级

190&#xff1a;JavaScript初级内容 - DOM查询、插入内容、赋予样式等 1、DOM操作 DOM&#xff1a;节点&#xff0c;也就是html中的元素&#xff1b; DOM操作&#xff1a;其实就是节点元素的方法&#xff1b; &#xff08;1&#xff09;innerHTML - 返回元素内容 同时也可以…

【JUC基础】05. Synchronized和ReentrantLock

1、前言 前面两篇中分别讲了Synchronized和ReentrantLock。两种方式都能实现同步锁&#xff0c;且也都能解决多线程的并发问题。那么这两个有什么区别呢&#xff1f; 这个也是一个高频的面经题。 2、相同点 2.1、都是可重入锁 什么是可重入锁&#xff1f; 可重入锁&#xff0…

Mysql查询字符串中某个字符串出现的次数

目录 1.查单个字符出现的次数2.查多个字符出现的次数3.函数讲解 1.查单个字符出现的次数 比如我想查how do you do 字符串当中出现d的次数&#xff1a; 第一眼看上去有点懵&#xff0c;首先mysql并没有直接计算出现字符次数的函数&#xff0c;所以才使用了下面这种方式&#x…

【排错记录】国产航顺HK32F030M驱动TM1624四位数码管显示

问题描述&#xff1a; 航顺单片机 HK32F030MF4P6用数码管显示驱动TM1624问题描述。 航顺单片HK32F030MF4P6的PC3/PC4/PC5引脚分别连接数码管驱动TM1624的DIN/CLK/STB;当单独使用HK32F030MF4P6单片机最小系统和TM1624数码管模块的时候部分最小系统板能驱动数码管正常显示&…

Centos 7 安装系列(11):Kibana

一、系统环境 操作系统&#xff1a;Centos 7 已安装环境&#xff1a;ElasticSearch 8.6.2 二、安装 需要注意的是&#xff1a;Kibana的版本需要和Elasticsearch保持一致。 2.1 下载并解压安装包 cd /opt yum install -y wget wget https://artifacts.elastic.co/downloads…

马哈鱼SQLFLow对SQL Server OUTPUT Clause 的数据血缘分析

SQL Server OUTPUT Clause 会对 SQL 语句的血缘分析产生影响&#xff0c;如果忽略对 OUTPUT Clause 的分析&#xff0c;那么将漏掉一些关键的数据血缘关系&#xff0c;从而影响数据血缘分析的准确性&#xff0c;进而影响组织的数据治理质量。 Gudu SQLFlow 可以对 SQL Server …