JUC-Synchronized原理进阶

轻量级锁

轻量级锁的使用场景:如果一个对象虽然有多线程要加锁,但加锁的时间是错开的(也就是没有竞争),那么可以使用轻量级锁来优化。轻量级锁对使用者是透明的,即语法仍然是 synchronized

假设有两个方法同步块,利用同一个对象加锁

static final Object obj = new Object();
public static void method1() {synchronized( obj ) {// 同步块 Amethod2();}
}
public static void method2() {synchronized( obj ) {// 同步块 B}
}
  • 创建锁记录(Lock Record)对象,每个线程都的栈帧都会包含一个锁记录的结构,内部可以存储锁定对象的 Mark Word

  • 让锁记录中 Object reference 指向锁对象,并尝试用 cas 替换 Object 的 Mark Word,将 Mark Word 的值存入锁记录

  • 如果 cas 替换成功,对象头中存储了锁记录地址和状态 00 ,表示由该线程给对象加锁,这时图示如下

  • 如果 cas 失败,有两种情况

    • 如果是其它线程已经持有了该 Object 的轻量级锁,这时表明有竞争,进入锁膨胀过程

    • 如果是自己执行了 synchronized 锁重入(从lock record的指向就可以知道是不是同一个线程),那么再添加一条 Lock Record 作为重入的计数

  • 当退出 synchronized 代码块(解锁时)如果有取值为 null 的锁记录,表示有重入,这时重置锁记录,表示重入计数减一

  • 当退出 synchronized 代码块(解锁时)锁记录的值不为 null,这时使用cas将Mark Word的值恢复给锁的对象头

    • 成功,则解锁成功

    • 失败,说明轻量级锁进行了锁膨胀或已经升级为重量级锁,进入重量级锁解锁流程

 锁膨胀

如果在尝试加轻量级锁的过程中,CAS 操作无法成功,这时一种情况就是有其它线程为此对象加上了轻量级锁(有 竞争),这时需要进行锁膨胀,将轻量级锁变为重量级锁。

  • 当 Thread-1 进行轻量级加锁时,Thread-0 已经对该对象加了轻量级锁,即对象的对象头的锁标志位是00,表示已是轻量级锁了。

  • 这时 Thread-1 加轻量级锁失败,进入锁膨胀流程

    • 即为 Object 对象申请 Monitor 锁,让 Object 的Mark Word指向重量级锁地址

    • 然后自己进入 Monitor 的 EntryList BLOCKED,进入阻塞队列等待。

  • 当 Thread-0 退出同步块解锁时,使用 cas 将 Mark Word 的值恢复给对象头,失败。这时会进入重量级解锁流程,即按照 Monitor 地址找到 Monitor 对象,设置 Owner 为 null,唤醒 EntryList 中 BLOCKED 线程

自旋优化

重量级锁竞争的时候,还可以使用自旋来进行优化,如果当前线程自旋成功(即这时候持锁线程已经退出了同步 块,释放了锁),这时当前线程就可以避免阻塞。如果发生阻塞,线程会从就绪态变为阻塞态,且会进行线程的上下文切换,耗费cpu资源

自旋重试成功的情况

线程1 ( core 1上)对象Mark线程2 ( core 2上)
-10(重量锁)-
访问同步块,获取monitor10(重量锁)重量锁指针-
成功(加锁)10(重量锁)重量锁指针-
执行同步块10(重量锁)重量锁指针-
执行同步块10(重量锁)重量锁指针访问同步块,获取 monitor
执行同步块10(重量锁)重量锁指针自旋重试
执行完毕10(重量锁)重量锁指针自旋重试
成功(解锁)01(无锁)自旋重试
-10(重量锁)重量锁指针成功(加锁)
-10(重量锁)重量锁指针执行同步块
-......

自旋重试失败的情况

线程1 ( core 1上)对象Mark线程2( core 2上)
-10(重量锁)-
访问同步块,获取monitor10(重量锁)重量锁指针-
成功(加锁)10(重量锁)重量锁指针-
执行同步块10(重量锁)重量锁指针-
执行同步块10(重量锁)重量锁指针访问同步块,获取monitor
执行同步块10(重量锁)重量锁指针自旋重试
执行同步块10(重量锁)重量锁指针自旋重试
执行同步块10(重量锁)重量锁指针自旋重试
执行同步块10(重量锁)重量锁指针阻塞
-......
  • 自旋会占用 CPU 时间,单核 CPU 自旋就是浪费,多核 CPU 自旋才能发挥优势

  • 在 Java 6 之后自旋锁是自适应的,比如对象刚刚的一次自旋操作成功过,那么认为这次自旋成功的可能性会 高,就多自旋几次;反之,就少自旋甚至不自旋,总之,比较智能。

  • Java 7 之后不能控制是否开启自旋功能

 

锁消除

JIT即时编译器会对代码进行优化,如果一个锁一直没有被其它线程竞争,只有一个线程持有,就会进行锁消除

@Fork(1)
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations=3)
@Measurement(iterations=5)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class MyBenchmark {static int x = 0;@Benchmarkpublic void a() throws Exception {x++;}@Benchmarkpublic void b() throws Exception {Object o = new Object();synchronized (o) {x++;}}
}

java -jar benchmarks.jar

Benchmark           Mode        Samples     Score       Score error     Units 
c.i.MyBenchmark.a   avgt        5           1.542           0.056       ns/op 
c.i.MyBenchmark.b   avgt        5           1.518           0.091       ns/op 

java -XX:-EliminateLocks -jar benchmarks.jar,禁止锁消除

Benchmark           Mode        Samples         Score       Score error     Units 
c.i.MyBenchmark.a   avgt        5               1.507       0.108           ns/op 
c.i.MyBenchmark.b   avgt        5               16.976      1.572           ns/op

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

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

相关文章

opencv处理图片(实战指南)

一、OpenCV简介 OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库。它拥有众多的图像处理和计算机视觉功能,包括各种常用的图像处理技术,如滤波、边缘检测、特征提取等。OpenCV支持多种编程语…

UDP 和TCP的应用

一、网络模型 (一)C/S 模型 客户端 / 服务器(Client/Server,C/S)模型是一种常见的网络架构。在这种模型中,客户端是主动的角色,向服务器发起请求;服务器端是被动的角色,…

electron-vite封装UI级的消息提示

说明 Electron Vite Vue3 Element Plus Electron中写提示有两种方案: 系统级:electron带的dialog相关APIUI级:UI框架内部的提示,如ElMessage、ElMessageBox、ElNotification等 今天来封装一下UI级别的提示 代码 效果图 源…

Springboot 定时任务cron表达式

Cron表达式是一个强大的字符串,用于在Unix/Linux系统中配置cron job(计划任务)的时间表。然而,在Spring框架(包括Spring Boot)中,Cron表达式也被广泛使用于Scheduled注解中,以定义定…

LLM之基于llama-index部署本地embedding与GLM-4模型并初步搭建RAG(其他大模型也可,附上ollma方式运行)

前言 日常没空,留着以后写 llama-index简介 官网:https://docs.llamaindex.ai/en/stable/ 简介也没空,以后再写 注:先说明,随着官方的变动,代码也可能变动,大家运行不起来,可以进…

巡检机器人的使用方法和维护保养

在当今快速发展的工业环境中,智能巡检机器人正逐渐成为提升运维效率和安全性的重要工具。旗晟机器人凭借其核心技术团队和多年的行业经验,推出了多款高效、智能的巡检机器人,旨在帮助企业实现设备运维的智能化升级。本文将介绍旗晟巡检机器人…

存储与传输/大小端字节序的概念、决定因素、给编程带来的困扰

文章目录 概述大小端分歧的类比为什么要关注字节序NET网络字节序什么时候必须转换字节序大小端字节序哪个优秀判断系统字节序类型字节序类型转换大小端内存监视和调试 谁决定了大小端模式CPU架构决定大小端操作系统影响大小端?编译器也影响大小端?可配置…

反射型XSS

反射型XSS(Cross-Site Scripting)是一种Web安全漏洞,它发生在当Web应用程序将用户输入的数据“反射”回浏览器,而没有进行适当的处理或编码时。这种类型的XSS攻击是非持久化的,意味着恶意脚本不会被永久存储在服务器上…

【威锋网-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 1. 暴力破解密码,造成用户信息泄露 2. 短信盗刷的安全问题,影响业务及导致用户投诉 3. 带来经济损失,尤其是后付费客户,风险巨大,造…

深度解析:常见本地大模型知识库工具部署、微调与对比,个人高效选型指南!

常见本地大模型知识库工具 LLM knowledge base 这里先盘点一下最近比较火爆的几个工具,将从知识库侧和大模型侧分别介绍。 01 知识库侧 知识库侧主要是指更加偏向于能够直接读取文档并处理大量信息资源,包括文档上传、自动抓取在线文档,…

Linux下进程间的通信--信号

信号的概念: 在Linux操作系统中,信号是一种软件中断机制,用于通知进程某个事件已经发生。信号是Linux进程间通信(IPC)的一种简单且快速的方式,它可以用来处理各种异步事件,如用户输入、硬件事件…

mysql 修改表的名字

mysql 修改表的名字 rename命令用于修改表名。 rename命令格式:rename table 原表名 to 新表名; 例如,在表MyClass名字更改为YouClass: mysql> rename table MyClass to YouClass; 当你执行 RENAME 时,你不能有任何锁定的表…

Redis (day 3)

一、通过jedis连接数据库 1.首先导入依赖 <!-- https://mvnrepository.com/artifact/redis.clients/jedis --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>5.1.0</version></de…

自己做的一个用于生成DICOM文件的服务器

框架: .ner core web api .net8.0 Program.cs代码如下 using Microsoft.AspNetCore.HttpsPolicy; using System.Diagnostics;namespace PacsServer {/* public class Program{public static void Main(string[] args){//配置服务var builder WebApplication.CreateBuilder(a…

(第三十三天)

1. 设置主从从 mysql57 服务器 &#xff08; 1 &#xff09;配置主数据库 [rootmsater_5 ~] # systemctl stop filewalld [rootmsater_5 ~] # setenforce 0 [rootmsater_5 ~] # systemctl disable filewalld [rootmsater_5 ~] # ls anaconda-ks.cfg mysql-5.7.44-linux-g…

Python实现贪心算法

目录 贪心算法简介贪心算法的基本思想贪心算法的应用场景活动选择问题 Python实现活动选择问题代码解释活动选择问题的解贪心算法的正确性分析贪心算法的其他应用贪心算法的局限性贪心算法的优化与变种总结 贪心算法简介 贪心算法&#xff08;Greedy Algorithm&#xff09;是一…

【Unity】通用GM QA工具 运行时数值修改 命令行 测试工具

GM工具使用: GM工具通常用于游戏运行时修改数值(加钱/血量)、解锁关卡等&#xff0c;用于快速无死角测试游戏。一个通用型GM工具对于游戏项目是非常实用且必要的&#xff0c;但通用不能向易用妥协&#xff0c;纯命令行GM门槛太高&#xff0c;对QA不友好。 这类运行时命令行工具…

进程的创建、终止

目录 前言1. 进程创建2. 进程终止3. exit && _exit 的异同3.1 相同点3.2 不同点 前言 紧接着进程地址空间之后&#xff0c;我们这篇文章开始谈论进程控制相关的内容&#xff0c;其中包括进程是如何创建的&#xff0c;进程终止的几种情况&#xff0c;以及进程异常终止的…

数学建模学习(115):主成分分析(PCA)与Python实践

文章目录 一.主成分分析简介1.1 数学背景与维度诅咒1.2 PCA的定义与应用二.协方差矩阵——特征值和特征向量三.如何为数据集选择主成分数量四.特征提取方法五.LDA——与PCA的区别六.PCA的应用七.PCA在异常检测中的应用八.总结一.主成分分析简介 1.1 数学背景与维度诅咒 主成成…

TOP10漏洞原理

## 本人为学习网安不久的新人&#xff0c;记一次学习笔记&#xff0c;有缺陷或者表述不对的地方欢迎大家指出&#xff0c;感谢&#xff01; ## 1、sql注入&#xff1a;web应用程序对用户输入的数据没有进行过滤&#xff0c;或者过滤不严&#xff0c;就把sql语句拼接进数据库…