【JAVA重要知识 | 第二篇】一篇文章读懂Java锁机制(含CAS思想、AQS机制)

news2024/9/23 13:29:22

文章目录

  • 2.一篇文章读懂Java常用的锁机制
    • 2.1锁介绍
      • 2.1.1定义
      • 2.1.2相关概念
    • 2.2锁的种类
      • 2.2.1按功能层面分
        • (1)共享锁/排他锁/读写锁
      • 2.2.2按性能和线程安全分
        • (1)乐观锁/悲观锁
        • (2)偏向锁/轻量级锁(自旋锁)/重量级锁(排他锁)
        • (3)公平锁/非公平锁
      • 2.2.3按锁的特性分
        • (1)重入锁(ReentrantLock)
        • (2)分布式锁
      • 2.2.4按锁的状态分
        • (1)死锁
        • (2)活锁
    • 2.3锁消除/锁膨胀
    • 2.4CAS思想
    • 2.5AQS机制
        • (1)概念
        • (2)AQS与Synchronized的区别
        • (3)常见的实现锁类
        • (4)基本工作机制

2.一篇文章读懂Java常用的锁机制

2.1锁介绍

2.1.1定义

在计算机科学中,锁(lock)或互斥(mutex)是一种同步机制,用于在有许多执行线程的环境中强制对资源的访问限制。锁旨在强制实施互斥排他、并发控制策略。

简单来说,锁要解决的问题就是 线程安全问题

所谓线程安全,主要体现在三方面:原子性、可见性和有序性。

  • 原子性:提供互斥访问,同一时刻只能有一个线程对数据进行操作。(synchronized、lock)
  • 可见性:一个线程对主内存的修改可以及时被其他线程看到。(volatile)
  • 有序性:一个线程观察其他线程的指令执行顺序,由于在JMM中允许编译器和处理器对指令重排序,因此该观察结果一般杂乱无序。(volatile)

2.1.2相关概念

需要了解关于锁的三个概念

1、锁开销 lock overhead :锁占用内存空间、 cpu初始化和销毁锁、获取和释放锁的时间。程序使用的锁越多,相应的锁开销越大

2、锁竞争 lock contention: 一个进程或线程试图获取另一个进程或线程持有的锁,就会发生锁竞争。锁粒度越小,发生锁竞争的可能性就越小

3、死锁 deadlock 至少两个任务中的每一个都等待另一个任务持有的锁的情况锁粒度是衡量锁保护的数据量大小,通常选择粗粒度的锁(锁的数量少,每个锁保护大量的数据),在当单进程访问受保护的数据时锁开销小,但是当多个进程同时访问时性能很差。因为增大了锁的竞争。相反,使用细粒度的锁(锁数量多,每个锁保护少量的数据)增加了锁的开销但是减少了锁竞争。例如数据库中,锁的粒度有表锁、页锁、行锁、字段锁、字段的一部分锁

相关术语 Critical Section(临界区)、 Mutex/mutual exclusion(互斥体)、 Semaphore/binary semaphore(信号量)

2.2锁的种类

以下将从功能层面、性能线程安全、锁的特性、以及锁的状态四个角度来分,锁一共可分为以下几种类型

  • 功能层面

    • 共享锁/排他锁/读写锁
  • 性能线程安全

    • 乐观锁/悲观锁
    • 偏向锁/轻量级锁(自旋锁)/重量级锁(排他锁)
    • 公平锁/非公平锁
  • 锁的特性

    • 重入锁/分布式锁
  • 锁的状态

    • 死锁/活锁

2.2.1按功能层面分

(1)共享锁/排他锁/读写锁

若从功能层面角度来看,锁可以分为三类:共享锁、排他锁、读写锁

  • 共享锁也叫读锁((ReadWriteLock),读锁的特点是在同一时刻允许多个线程抢占到锁
  • 排它锁也叫写锁(ReentrantLock、 Synchronized),写锁的特点是在同一时刻只允许一个线程抢占到锁。

锁升级:读锁到写锁 (不支持)

锁降级:写锁到读锁 (支持)

《共享锁(读锁)/排他锁(写锁)》详情笔记链接:暂无

  • 读写锁 ReentrantReadWriteLock

低16位代表写锁,高16位代表读锁

  1. 该读写锁 ReentrantReadWriteLock提供了一个读锁,支持多个线程共享同一把锁。
  2. 它也提供了一把写锁,是排他锁,和其他读锁或者写锁互斥,表明只有一个线程能持有锁资源。

通过两把锁的协同工作,能够最大化的提高读写的性能,特别是读多写少的场景,而往往大部分的场景都是读多写少的。

《读写锁 ReentrantReadWriteLock》详情笔记链接:暂无

2.2.2按性能和线程安全分

(1)乐观锁/悲观锁
  • 乐观锁

    1. 每次去读取数据时,都认为其他人不会修改该数据,因此不会加锁
    2. 修改数据,提交更新时候会判断在此期间是否有他人去更新此数据
    3. 使用版本号机制和CAS算法实现
  • 悲观锁

    1. 总是假设最坏的情况,每次去 拿(读取/修改) 数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁
    2. Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现

《乐观锁/悲观锁》详情笔记链接:暂无

(2)偏向锁/轻量级锁(自旋锁)/重量级锁(排他锁)
  • 偏向锁

    • 定义:可以让同一线程一直拥有同一个锁,直到出现竞争,才去释放锁!
    • 场景:应用于同步代码块在大多数情况下只有同一个线程访问
    • 举例:所谓偏向锁就是当线程1进入锁的时候如果当前不存在竞争,那么它就会把这个锁偏向线程1,线程1下次再进入的时候,就不再需要竞争锁
  • 轻量级锁(自旋锁)

    • 定义:轻量级锁即通过自旋方式不断尝试获取锁,而不是阻塞。当偏向锁被其他线程访问后,就会升级为轻量级锁。常见的轻量级锁即自旋锁
    • 场景:前提是线程在临界区的操作非常快,所以它会非常快速地释放锁
  • 重量级锁(排他锁)

    • 定义:有一个线程获取锁之后,其余所有等待获取该锁的线程都会处于阻塞状态
    • 场景:有大量的线程参与锁的竞争,冲突性很高

《偏向锁/轻量级锁(自旋锁)/重量级锁(排他锁)》详情笔记链接:暂无

(3)公平锁/非公平锁
  • 公平锁:每个线程获取锁的顺序按照线程访问锁的先后顺序获取的;
  • 非公平锁:每个线程获取锁的顺序是随机的,并不会遵循先来后到的规则,所有线程会竞争获取锁。

默认情况下锁都是非公平的,比如Synchronized(只能为非公平锁)、Reentrantlock(在创建Reentrantlock时可以手动指定成公平锁)

因为非公平锁的性能要比公平锁的性能更好,非公平锁意味着减少了锁的等待减少了线程的阻塞和唤醒

《公平锁/非公平锁》详情笔记链接:暂无

2.2.3按锁的特性分

第三维度从锁的特性来说,又会有重入锁和分布式锁。

(1)重入锁(ReentrantLock)

锁主要用来控制多线程访问问题,对于同一线程,如果连续两次对同一把锁进行加锁,那么这个线程就会被卡死

在实际开发中,方法之间的调用错综复杂,一不小心就可能在多个不同的方法中反复调用lock(),造成死锁

重入锁:同一线程可以对同一把锁在不释放的前提下,反复加锁不会导致线程卡死,唯一的一点就是需要保证lock()和unlock0)的次数相同

(2)分布式锁

分布式锁是解决分布式架构下粒度的问题,解决的是进程维度的问题,而Synchronized是解决Java并发里面的线程维度。关于分布式锁更多知识点后面我们单独来讨论。

《重入锁/分布式锁》详情笔记链接:暂无

2.2.4按锁的状态分

(1)死锁
  • 定义:指两个或两个以上的线程在执行过程中,因争夺资源造成的一种互相等待的现象。当一个线程永久地持有一把锁后,其他线程将永久等待下去

  • 四个条件:

    • 互斥性:即线程占用的锁是互斥锁,不能被其他为占用的线程访问
    • 不剥夺:即线程已经获得锁,在未主动释放之前,不会被其他线程剥夺
    • 请求和保持:即有锁S1,S2,线程一持有了S1,又发起了对S2的持有请求。而同时有线程二持有了S2,又发起了对S1的持有请求。
    • 环路等待:即死锁发生时,必然有一个环形链。如{p0,p1,p2,…pn}。p0等待p1释放资源,p1等待p2释放资源,p2等待p3释放资源,… pn等待p0释放资源
  • 解决方式:

    • jstack定位死锁:https://www.cnblogs.com/chenpi/p/5377445.html
    • 线上环境死锁,查看堆栈信息:使用 jps和jstack 命令分别查看JVM中运行的进程状态信息、以及java进程内线程的堆栈信息
  • 死锁避免:

    • 避免相反的获取锁的顺序
    • 设置超时时间(lock类的 tryLock)
    • 多使用并发类而不是自己设计锁
(2)活锁
  • 定义:活锁即线程并没有阻塞,也始终在运行,但是程序却得不到进展,因为线程始终重复做同样的事。本质原因是重试机制一样,始终互相谦让
  • 案例:例如消息队列,若消息队列第一个一直消费失败,则会不断进行重试。而非第一个消息则会一直等待第一个消息被消费,造成了整个队列的罢工
  • 解决方案:
    • 增加随机因素
    • 增加重试机制

2.3锁消除/锁膨胀

在jdk中还引入了锁消除和锁膨胀,这是编译器层面的优化,主要优化加锁的性能。

  • 锁消除:代码本身可能就没有线程安全问题,但是你又加了锁,然后ivm编译的时候发现这个地方加了锁,导致无效竞争,那么它就会把这个锁消除掉。
  • 锁膨胀:因为控制的锁粒度太小,导致频繁加锁和释放锁,所以它就会把锁的范围扩大。

2.4CAS思想

  1. 定义:CAS即Compare And Swap,比较后再交换,体现了乐观锁思想,在无锁情况下保证线程操作共享数据的原子性

  2. 数据交换流程:

    image-20240303102641948

  3. 底层:

    image-20240303102706007

2.5AQS机制

(1)概念

AQS即AbstractQueuedSynchronizer,即抽象队列同步器,为构建锁或者其他同步组件的基础框架

同步器功能屏蔽了一些锁内部实现的细节例如:线程的等待排列,锁的实现,同步状态的管理,等待和唤醒等,让锁的使用者能够简单的使用锁

(2)AQS与Synchronized的区别

image-20240303102827591

(3)常见的实现锁类
  1. ReentrantLock:可重入锁
  2. ReentrantReadWriteLock:读写锁
  3. Semaphore:信号量
  4. CountDownLatch:倒计时锁
(4)基本工作机制
  1. AQS内部维护一个先进先出的双向队列,存储排队获取锁的线程
  2. AQS内部有一个属性state,相当于是一个资源, 默认为0;若队列中有一个线程将state修改了为 1,则意味着当前线程获取了资源
  3. 原子性:对state修改时,使用cas操作,保证了 多个线程修改的原子性

《深入理解AQS原理与Reentrantlock锁》笔记:https://blog.csdn.net/weixin_61440595/article/details/136442636

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

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

相关文章

盘点:国家智能算力中心

文章目录 1. Main2. My thoughtsReference 1. Main 按照《中国算力白皮书(2022年)》的定义,算力主要分为四部分:通用算力、智能算力、超算算力、边缘算力。通用算力以CPU芯片输出的计算能力为主;智能算力以GPU、FPGA、…

如何本地创建websocket服务端并发布到公网实现远程访问

文章目录 1. Java 服务端demo环境2. 在pom文件引入第三包封装的netty框架maven坐标3. 创建服务端,以接口模式调用,方便外部调用4. 启动服务,出现以下信息表示启动成功,暴露端口默认99995. 创建隧道映射内网端口6. 查看状态->在线隧道,复制所创建隧道的公网地址加端口号7. 以…

使用easyexcel填充模板数据,并导出excel

文章目录 前言一、制作模板二、前端代码三、后端代码总结 前言 导出excel功能非常场景,本片文章记录如何使用模板填充数据后再导出。因直接导出excel数据样式不符合要求,所以做了模板填充然后再导出excel。 效果如下: 一、制作模板 注意&a…

2024年腾讯云服务器优惠券领取入口及使用教程

随着云计算技术的不断发展,越来越多的企业和个人选择将业务迁移到云端。腾讯云作为国内领先的云计算服务提供商,为了吸引用户上云,经常推出多种优惠活动,其中就包括服务器优惠券,本文将为大家分享腾讯云服务器优惠券的…

华为配置基于VLAN限速示例

华为配置基于VLAN限速示例 组网图形 图1 流量监管配置组网图 表1 Switch为上行流量提供的QoS保障 流量类型 CIR(kbps) PIR(kbps) DSCP优先级 语音 2000 10000 46 视频 4000 10000 30 数据 4000 10000 14 ^^^ 流分类简介配置注意事项组网需求配置思路操作步…

恒峰-智能高压森林应急消防泵:守护森林安全的绿色战士

在茂密的森林中,每一棵树木都是大自然的精灵,它们为我们提供氧气、净化空气、保持水土,是地球上不可或缺的生命之源。然而,当火灾肆虐时,这些树木也会成为我们的噩梦。为了保护森林资源,我们需要一种高效、…

TikTok外贸系统的核心功能及其源代码分享!

随着全球化的不断推进,外贸业务成为越来越多企业的增长动力,TikTok作为一个全球性的社交媒体平台,其用户基数庞大、活跃度高,为外贸业务提供了无限的商机。 为了帮助企业在TikTok上更好地开展外贸业务,TikTok外贸系统…

数据持久层框架:MyBatis

数据持久层框架:MyBatis 前言入门SqlSessionFactorySqlSession作用域(Scope)和生命周期 配置properties(属性)settings(设置)typeAliases(别名)typeHandlers(…

Deep Learning相关概念介绍

工具: Anaconda: anaconda.com/products/individual。我理解是一个基于Python的AI程序开发环境,其作用类似于google notebook。区别是google notebook是在网页上,而Anaconda一般是安装在自己的服务器上。Jupyter Notebooks Anaconda激活深度…

Linux - 安装 maven(详细教程)

目录 一、下载二、安装三、配置环境变量四、镜像资源配置 一、下载 官网:https://maven.apache.org/download.cgi 打开 maven 的官网下载页面,点击 bin.tar.gz 文件链接 即可下载最新版本的 maven 如果想要下载旧版本的 meven,则点击 Maven…

JavaScript中call和apply函数方法

看下下面这个代码示例: javascript const lufthansa {airline: Lufthansa,iataCode: LH,bookings: [],book(flightNum, name) {console.log(${name} booked a seat on ${this.airline} flight ${this.iataCode}${flightNum});}, };lufthansa.book(239, ‘IT知识一…

python实现有限域GF(2^8)上的乘法运算

有限域GF(2^8)上的乘法运算可以看成多项式的乘法 5e转换成二进制为0101 1110,对应的多项式为x^6x^4x^3x^2x 3f转换成二进制为0011 1111,对应的多项式为x^5x^4x^3x^2x1 将这两个多项式相乘再模多项式x^8x^4x^3x1得到结果为1110 0101,转换为…

【扩散模型】生成模型中的Residual Self-Attention UNet 以及 DDPM的pytorch代码

参考: [1] https://github.com/xiaohu2015/nngen/blob/main/models/diffusion_models/ddpm_cifar10.ipynb [2] https://www.bilibili.com/video/BV1we4y1H7gG/?spm_id_from333.337.search-card.all.click&vd_source9e9b4b6471a6e98c3e756ce7f41eb134 TOC 1 UNe…

Vue3+vite+vant UI移动端项目创建保姆级教程

项目创建 创建Vue3项目 npm create vue@latestcd shoujihao-h5npm installnpm run formatnpm run dev修改端口 vue3 默认端口5173 想要把端口号修改为8088,在vite.config.js中写入 server: {port: 8088,//端口号host: true,//ip地址 或 0.0.0.0 或 "loaclhost"o…

OSCP靶场--Walla

OSCP靶场–Walla 考点(1.hydra http基本认证爆破: 2.sudo -l:python导入外部模块提权 3.Linux内核提权:cve-2021-4034) 1.nmap扫描 ## ┌──(root㉿kali)-[~/Desktop] └─# nmap -sV -sC -p- 192.168.181.97 --min-rate 2000 Starting N…

浅谈二进制漏洞研究与病毒研究

安全方向 最近一些朋友找到我,说想学习一下漏洞和病毒研究,其实很多安全研究人员想入门二进制安全,但关于二进制安全,很多新手朋友对这个方向不太了解,也不知道该怎么去深入的研究学习二进制安全,如何才能…

装修必看干货|入户玄关设计进门就是客厅应该怎么设计?福州中宅装饰,福州装修

入户玄关设计在进门就是客厅的情况下,想要拥有单独的玄关空间,以下是五点设计建议: ①隔断屏风 使用隔断屏风是传统而常见的一种空间分割方法。可以选用木制、金属或玻璃等材质的屏风,根据需要进行灵活搭配和定制。 屏风的款式和…

项目可行性方案:人脸识别实现无感考勤的项目技术可行性方案

目 录 1.引言 1.1编写目的 1.2背景 2.可行性研究的前提 2.1要求 2.2目标 3.对现有系统的分析 3.1系统改进示意图 3.2改进之处 3.3技术条件方面的可行性 4.结论 1.引言 1.1编写目的 本报告编写的目的是探究学校里对教室和办公室内教师的人脸进行识别从而…

Kubernetes-1

学习Kubernetes第一天 k8s-11、什么是Kubernetes2、配置Kubernetes2.1、准备三台全新的虚拟机2.2、关闭防火墙和SElinux2.3、修改主机名2.4、升级操作系统(三台一起操作)2.5、配置主机hosts文件,相互之间通过主机名互相访问2.6、配置master和node之间的免密通道2.7、…

Linux虚拟文件系统管理技术

Linux虚拟文件系统管理技术 1. 虚拟文件系统的组成1.1 虚拟文件系统架构1.2 超级块(super block)1.3 索引节点(inode)1.3.1 inode怎样生成的?1.3.2 inode和文件的关系? 1.4 目录项(dentry)1.5 文件对象(file) 2. 进程与文件系统的关系3. 磁盘与文件系统的关系4. 常见的文件系…