Synchronized锁的升级流程详解

在Java多线程编程中,synchronized关键字用于确保在同一时刻只有一个线程可以访问被锁定的资源,从而维护数据的一致性和安全性。然而,在多线程环境中,锁的频繁获取和释放会带来性能开销。为了提高性能,Java虚拟机(JVM)在JDK 1.6及以后的版本中引入了锁的升级机制,通过动态调整锁的策略来减少同步操作的开销。本文将详细解释synchronized锁的升级流程,包括无锁状态、偏向锁、轻量级锁和重量级锁四种状态及其转换过程。

锁的状态

无锁状态

当一个对象刚被创建时,它处于无锁状态,此时没有线程持有锁,所有访问同步代码块的线程都是无锁竞争状态。在这种状态下,对象的Mark Word(对象头的一部分,用于存储锁状态及线程信息)没有记录任何锁信息。

偏向锁

偏向锁是为了解决单线程访问共享资源的场景而设计的。当一个线程首次获得对象锁时,JVM会将锁设置为偏向锁,并将锁对象的Mark Word中的线程ID设置为当前线程的ID。后续当这个线程再次请求相同的锁时,只需检查Mark Word中的线程ID是否与当前线程ID一致。如果一致,说明还是原来的线程持有锁,可以直接进入同步代码块,无需进行额外的同步操作。偏向锁减少了轻量级锁中CAS操作的开销,提高了性能。

轻量级锁

当有第二个线程尝试获取已被偏向锁锁定的对象时,偏向锁失效,JVM会尝试升级为轻量级锁。线程会在当前线程栈中创建一个锁记录(Lock Record),并将锁对象的Mark Word替换为指向锁记录的指针,同时在锁记录中存储当前线程的ID和一个指向原Mark Word副本的指针。使用CAS操作尝试将锁对象的Mark Word设置为指向锁记录的指针。如果成功,线程获得轻量级锁并执行同步代码;如果失败(即有其他线程已持有锁),则进入下一步骤。轻量级锁适用于短暂的、低竞争的同步场景,通过自旋等待和CAS操作避免了线程切换的开销。

重量级锁

当自旋尝试失败或自旋超过一定阈值,或者系统检测到多个线程长期竞争同一锁时,轻量级锁会升级为重量级锁。重量级锁通常涉及操作系统级别的互斥量(Mutex),线程在无法获得锁时会被挂起,不再消耗CPU资源,直到持有锁的线程释放锁后,操作系统再唤醒等待队列中的下一个线程。重量级锁提供了严格的互斥保证,适用于高竞争或锁占用时间较长的场景,虽然开销较大,但能有效防止过多线程同时阻塞在自旋状态。

Mark Word

Mark Word是对象头中最重要的部分,它是一个特殊的字段,用于存储对象的元数据信息,包括锁状态和线程信息。在64位JVM中,Mark Word占用64位。当一个共享资源首次被某个线程访问时,锁就会从无锁状态升级到偏向锁状态,偏向锁会在Mark Word的偏向线程ID里存储当前线程的操作系统线程ID,偏向锁标识位是1,锁标识位是01。此后如果当前线程再次进入临界区域时,只比较这个偏向线程ID即可。

锁升级流程

无锁状态到偏向锁

当一个对象首次被某个线程访问时,它处于无锁状态。当第一个线程访问同步代码块或方法时,JVM会将对象头的Mark Word设置为偏向锁,并记录这个线程的ID。此时,如果后续的访问仍然是由这个线程发起的,无需进行同步操作,直接执行代码即可,因为锁已经偏向于这个线程。

偏向锁到轻量级锁

如果有其他线程尝试访问这个同步块,偏向锁将被撤销,并进入轻量级锁状态。撤销时会有一定的开销,包括检查偏向锁标识、CAS操作尝试清除偏向锁等。当有第二个线程尝试获取锁时,偏向锁被撤销,转换为轻量级锁。线程会在自己的栈帧中创建一个称为Lock Record的空间,用于存储锁的Mark Word的拷贝。然后通过CAS操作尝试将对象头的Mark Word替换为指向Lock Record的指针。如果成功,线程获得锁;失败,则说明存在竞争,线程将自旋一段时间,不断尝试CAS操作直到成功或达到自旋上限。

轻量级锁到重量级锁

如果自旋超过一定次数(自旋阈值)仍未获得锁,轻量级锁将升级为重量级锁。此时,JVM会调用操作系统的互斥量(mutex)来实现线程阻塞和唤醒,这会导致线程挂起和恢复,开销较大。未获取到锁的线程会被阻塞,进入等待队列,而持有锁的线程执行完毕后,会唤醒队列中的下一个等待线程。

锁升级过程中的关键概念

CAS操作

CAS(Compare and Swap)操作是一种无锁算法,用于在多线程环境下实现原子操作。它比较内存中的值与预期值是否相等,如果相等则更新为新值,否则不做任何操作。在轻量级锁的获取过程中,CAS操作用于尝试将对象头的Mark Word替换为指向Lock Record的指针。

自旋锁

自旋锁是一种轻量级的锁机制,当线程尝试获取锁失败时,它不会立即被阻塞,而是会在一个循环中不断尝试获取锁,直到成功或达到某个条件(如自旋次数上限)。自旋锁避免了线程切换的开销,但在高竞争场景下可能会导致CPU资源的浪费。

自适应自旋

自适应自旋的基本思想是根据锁的争用情况,决定线程是否应该自旋等待,以及自旋等待的时间。JVM会根据历史数据动态调整自旋的次数,以减少不必要的自旋开销。

锁升级的意义

锁的升级过程是为了提高多线程环境下的性能和吞吐量,减少同步操作的开销,并尽量避免线程切换的开销。在大多数情况下,锁是由单个线程持有的,如果直接使用重量级锁,会浪费资源。因此,JVM根据线程竞争的情况和锁的使用情况自动进行锁的升级和降级,以优化多线程程序的性能。

代码示例

以下是一个简单的代码示例,展示了synchronized锁的升级过程:

public class SynchronizedExample {  // 对象锁示例  public synchronized void method1() {  System.out.println("Method 1 executing by " + Thread.currentThread().getName());  try {  Thread.sleep(2000); // 模拟耗时操作,增加锁竞争的可能性  } catch (InterruptedException e) {  e.printStackTrace();  }  }  // 代码块锁示例,锁定的是object实例  private Object object = new Object();  public void method2() {  synchronized (object) { // 这里使用的是对象锁  System.out.println("Method 2 executing by " + Thread.currentThread().getName());  try {  Thread.sleep(2000); // 模拟耗时操作  } catch (InterruptedException e) {  e.printStackTrace();  }  }  }  public static void main(String[] args) {  SynchronizedExample example = new SynchronizedExample();  Thread t1 = new Thread(() -> example.method1(), "Thread-1");  Thread t2 = new Thread(() -> example.method2(), "Thread-2");  t1.start();  t2.start();  }  
}

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

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

相关文章

计算机组成原理(笔记7高速缓冲存储器Cache,计算机组成原理的重难点全、直接、组相连)

为什么要设立高速缓冲存储器 (Cache)? Cache是介于CPU和主存之间的小容量存储器,存取速度比主存快。它能高速地向CPU提供指令和数据,加快程序的执行速度。它是为了解决CPU和主存之间速度不匹配而采用的一项重要技术。…

10月15日,每日信息差

第一、《哈利・波特与魔法石》在中国内地总票房突破 3 亿元,包括 2002 年首映的 5600 万,2020 年重映的 1.923 亿,以及 2024 年重映的 5170 万。 第二、全国铁路实施新货物列车运行图,增开城际班列至 131 列,多式联运…

qiankun-前端接入微服务vue3项目应用

背景 由于在 《吐槽一次qiankun微前端的框架》 这篇博客中,初次使用qiankun,然后接入了原生项目作为微服务的应用到主应用,所以就想着出个系列篇 目的 介绍利用qiankun框架, vue3 项目应用作为微应用,怎么接入到主应…

节点+镜像

节点、镜像: 在服务器领域,"节点" 和 "镜像" 是两个关键的概念,常与分布式系统、云计算或集群相关联。以下是对它们的详细解释: 1. 服务器节点 在分布式系统或云计算环境中,节点指的是网络中执行特定任务的…

使用Mockaroo生成测试数据

使用Mockaroo生成测试数据 最近在学习【Spring Boot & React】Spring Boot和React教程视频的P51.Generating 1000 students一课中,看到了https://www.mockaroo.com/网站可以用来模拟生成测试数据,觉得还不错,特此记录一下。感觉每次看老…

centOS部署Jenkins实现项目可持续自动化部署

个人看的是尚硅谷的视频,跟着实战,但因为视频是21年的,所以很容易出现jenkins插件不适配问题。 因而个人直接用较新版的jdk和jenkins. 先切换到root用户 sudo su一、安装jdk 先查询可安装版本 yum list java*安装jdk(只复制圈…

【Python爬虫实战】正则:中文匹配与贪婪非贪婪模式详解

🌈个人主页:https://blog.csdn.net/2401_86688088?typeblog 🔥 系列专栏:https://blog.csdn.net/2401_86688088/category_12797772.html 目录 前言 一、匹配中文 (一)匹配单个中文字符 (二…

数据结构常考基础代码题-顺序表有序插入

顺序表递增有序,插入元素 x,仍递增有序 第一步:定义顺序表结构体 根据题目中的“顺序表递增有序”,我们需要定义一个顺序表结构体,用于存储元素和顺序表的相关信息。 typedef struct {int *data; // 动态数组存储元…

DeepFM模型代码详解

直到看到这篇文章,我才搞明白类别特征怎么做lookup的,也看明白了代码逻辑。如果你看完没懂,私信留下wx,给你讲懂。 1、Deepfm 的原理,DeepFM 是一个模型还是代表了一类模型,DeepFM 对 FM 做了什么样的改进…

单细胞copyKat分析学习和整理

CopyKAT(肿瘤拷贝数核型分析)是一种使用综合贝叶斯方法的计算工具,能够在单细胞中以5MB分辨率检测全基因组非整倍体,以便从高通量单细胞RNA测序数据中区分肿瘤细胞与正常细胞,并识别肿瘤亚克隆。 (这里提一下,“5MB”是指 5兆碱基对(5 megab…

JSP复习(二)

九大内置对象 在 JSP(JavaServer Pages)中,有九大内置对象,这些对象为开发者提供了常用的功能,帮助简化 JSP 页面中的处理。以下是这九大内置对象: request:表示客户端请求的对象,可…

CTF-PWN方向 栈溢出等基础知识笔记(2)

C语言基本函数补充 write函数 ret2syscall 要求有0x80这种系统调用存在 (0x0A是回车的意思) 案例 通过file查看这个文件 发现是静态编译的文件 所以很多库函数都被编译进去了 但是不存在bin/sh字符串 不存在system和backdoor函数 修改,rea…

纯手柄控制电脑(且不用插鼠标而使用虚拟鼠标)

前言 因电脑升级后,旧主机就作为客厅游戏机使用了,于是想尽量减少设备的插入,单纯的每次只拔插手柄这一项外设就行,于是需要两大步骤即可到位。 安装JoyXoff 一、官网下载并直接安装:JoyXoff 二、默认开机自启&…

【环境搭建】远程服务器搭建ElasticSearch

参考: 非常详细的阿里云服务器安装ElasticSearch过程..._阿里云服务器使用elasticsearch-CSDN博客 服务器平台:AutoDL 注意: 1、切换为非root用户,su 新用户名,否则ES无法启动 2、安装过程中没有出现设置账号密码…

AD9361 在低至 1MHz 的频率下运行

AD9361 在低至 1MHz 的频率下运行 AD -FREQCVT1-EBZ是包含AD9361的FMCOMMS3/4/5板的附加板。虽然完整的芯片级设计包可在此 RF 收发器的ADI产品页面上找到,但有关此卡的信息及其使用方法、围绕它的设计包以及可使其工作的软件可在此处找到。 AD-FREQCVT1-EBZ 模块…

山西农业大学20241015

02-VUE 一. Vue中常用的指令1. Vue指令概述2 Vue中指令的分类3 Vue中指令3.1 内容渲染指令3.2 条件渲染指令3.2.1 v-show3.2.2 v-if3.2.3 v-else 和 v-else-if 3.3 事件绑定指令 v-on--重要3.3.1 内联语句3.3.2 methods中的函数名 一. Vue中常用的指令 1. Vue指令概述 概念: 指…

安装Node.js环境,安装vue工具

一、安装Node.js 去官方网站自行安装自己所需求的安装包 这是下载的官方网站 下载 | Node.js 中文网 给I accept the terms in the License Agreement打上勾然后点击Next 把安装包放到自己所知道的位置,后面一直点Next即可 等待它安装好 然后winr打开命令提示符cmd 二、安装…

MySQL中表的约束

1,概念 表中一定要有各种约束,通过约束,让我们来插入数据库中的数据是符合预期的。 约束本质是通过技术手段,倒逼程序员插入正确的数据;反过来,站在MySQL的角度来单,内部已经插进来的数据&…

YOLOv11改进策略【卷积层】| ParNet 即插即用模块 二次创新C3k2

一、本文介绍 本文记录的是利用ParNet中的基础模块优化YOLOv11的目标检测网络模型。 ParNet block是一个即插即用模块,能够在不增加深度的情况下增加感受野,更好地处理图像中的不同尺度特征,有助于网络对输入数据更全面地理解和学习,从而提升网络的特征提取能力和分类性能…

Web安全 - 跨站点请求伪造CSRF(Cross Site Request Forgery)

文章目录 OWASP 2023 TOP 10CSRF 导图CSRF的基本概念CSRF的工作原理常见CSRF攻击模式CSRF防御策略补充建议应用场景实战防御策略选择1. CSRF Token(首选)2. SameSite Cookie属性3. 验证Referer和Origin4. 多因素认证 实现方案CSRF Token实现SameSite Coo…