当前位置: 首页 > news >正文

深入理解synchronized的原理是什么

对象头锁机制原则

在这里插入图片描述

Synchronized 的原理是什么

  Synchronized 是由JVM实现的一种实现互斥同步的实现方式。如果查看synchronized关键字修饰的字节码,会发现在编译器生成了monitorenter和monitorexit两个字节码指令。
在这里插入图片描述
  这两个指令的意思就是在虚拟机执行到monitorenter指令的时候,首先尝试获取到对象锁,对象头这部分在对象的最前端,包含两部分或者三部分:Mark Words、Klass Words,如果对象是一个数组,那么还可能包含第三部分:数组的长度。Mark Word需要重点说一下,这里面主要包含对象的哈希值、年龄分代、锁标志位等,大小为32位或64位
在这里插入图片描述
  如果这个对象没有锁定,或者当前线程已经拥有了这个对象锁,那么就把锁的计数器进行+1操作,当执行monitorexit指令的时候将锁计数器进行-1操作,当计数器为0的时候,锁就被释放了。
  如果获取对象失败了,当前线程就要阻塞等待,直到对象锁被另外一个线程释放。

刚刚提到的对象所,这个锁到底是什么?如何确定对象的锁?

  锁 的本质是monitorenter和monitorexit 字节码指令的一个Reference类型的参数,也就是是要锁定和解锁的对象。
  Synchronized可以修饰不同的对象,所以对应的对象锁可以通过如下的方式确定

  • 1、如果Synchronized明确指定了锁定对象,说明加锁对象为该对象。
  • 2、如果没有明确指定:
     如果Synchronized修饰的方法为非静态方法,表示此方法对应的对象为锁对象;
     如果Synchronized修饰的方法为静态方法,则表示这个方法对应的类对象为锁对象。

  需要注意的是,当一个对象被锁住的时候,对象里面所有用synchronized修饰的方法都将会被阻塞,而对象里非synchronized修饰方法可以正常被调用,不受到影响。

什么是可重入性,为什么synchronized是可重入锁?

  可重入性是锁的基本要求,是为了解决死锁的情况发生。
在这里插入图片描述
  如图所示,在一个类中同步调用了另一个同步方法,假如synchronized不支持重入,进入method2的时候当前线程获取锁,method2中又执行了method1的时候当前线程又要尝试获取锁,这个时候如果不支持重入,那就要等待释放,所以自己获取锁,自己等释放,就会导致死锁。

  对于synchronized来说,重要性是显而易见的。在执行monitorenter指令的时候 ,如果这个对象没有锁定,或者当前线程已经拥有了这对象锁,就把锁的计数器加一,实际上就是通过这种机制来实现锁重入。

JVM对于Java的原生锁做了那些优化

  在Java6之前Monitor实现完全依赖底层操作系统的互斥锁来实现,也就是在上面提到的获取/释放锁的逻辑。

  由于Java层面的线程与操作系统的原生线程有对应的映射关系,如果要将一个线程进行阻塞或者唤醒都需要操作系统线程的协助,也就是从用户态到内核态的切换,这种相互之间的切换其实是一件非常消耗内存的事情。

  所以JDK对于这种操作进行了很多的优化。

 使用自旋锁,也就是说把线程进行阻塞操作之前让线程自旋等待一段时间,可能在等待的时候其他线程已经解锁了,这个时候就不需要线程在等待了,避免了用户态到内核态的切换。

 在JDK中提供了三种不同的Monitor的实现,也就是三种不同的锁机制。

  • 偏向锁
  • 轻量级锁
  • 重量级锁

  这三种锁机制使得JDK对于synchronized的优化进行进一步的提升,当JVM检测到不同的资源竞争状况的时候,会自动切换到合适的锁实现机制,也就是所谓的锁的升级与降级。

  当没有出现竞争的时候,默认使用的是偏向锁。

  JVM会利用CAS操作,在对象头的MarkWord部分设置线程ID,以表示这个对象偏向于当前线程,所以并不涉及真正的互斥锁,因为在很多应用场景中,大部分对象生命周期中最多会被一个线程锁定,使用偏向锁可以降低无竞争开销。

  如果有一个线程试图锁定偏向锁对象的时候,JVM就撤销偏向锁,切换到轻量级锁。

  轻量级锁通过CAS操作Mark Word来试图获取锁,如果重试成功,就使用普通的轻量级锁,否则就升级为重量级锁。

为什么说synchronized是非公平锁?

  非公平主要表现在获取锁的行为上,并非按照申请锁的时间前后给等待线程分配锁,每当锁被释放之后,任何一个线程都有机会竞争到锁,这样做的目的是为了提高执行性能,缺点是会产生线饥饿现象。

什么是锁消除和锁粗化?

  • 锁消除:指虚拟机及时编译器在运行时,对一些代码上要求同步,但被检测到不可能存在共享数据竞争的锁进行消除。主要根据逃逸分析。开发者怎么会在明知道不会存在数据竞争的情况下使用同步操作呢?很多的操作其实不是开发者自己加入的。
  • 锁粗化:原则上,同步块的作用范围要尽量小。但是如果一系列的连续操作都对同一个对象反复加锁和解锁,甚至加锁操作在循环体内,频繁地进行互斥同步操作也会导致不必要的性能损耗。锁粗化就是增加锁的作用域。

为什么说 synchronized是一个悲观锁?乐观锁的实现原理又是什么?什么是CAS,它有什么特性?

  synchronized是一个悲观锁,因为他的并发策略是悲观的,不管是否会产生竞争,任何的数据都必须要加锁、用户态核心态转换、维护锁计数器和检查是否有被阻塞的线程需要被唤醒等操作。

  随着硬件指令集的发展,可以使用基于冲突检测的乐观锁并发策略。先进性操作,如果没有其他线程征用数据,那么就操作成功。

  如果共享数据有被用到,产生了冲突,那就再进行其他的补偿措施。这种乐观的并发策略的许多实现不需要线程挂起,所以被称为非阻塞同步。

  乐观锁的核心算法是CAS(Compareand Swap,比较交换),涉及到三个操作数:内存值、预期值、新值。当且仅当预期值和内存值相等的时候才将内存值修改新值。

  这样处理的逻辑是,首先检查某块内存的值是否跟之前读取过的值一样,如果不一样则表示期间此内存值已经被别的线程修改过了,舍弃本次操作,否则则说明在此期间没有其他线程对此内存值进行修改,就可以直接使用该值。

  CAS具有原子性,他的原子性有CPU硬件指令实现保证,即使用JNI调用Native方法调用C++编写的硬件指令,JDK中提供了Unsafe类执行这些操作。

乐观锁一定就是好的?

  乐观锁避免了悲观锁独占对象的现象,同时也提高了并发性能,但它的缺点:

  • 1、乐观锁只能保证一个共享变量的原子性操作,如果多一个或者几个变量,乐观锁就有点力不从心了,但互斥锁能轻易地解决该问题,不管对象数量多少以及对象大小。
  • 2、长时间自旋操作可能导致开销较大,加入CAS长时间不成功而一直自旋,就会导致CPU消耗过大。
  • 3、ABA问题,CAS的核心思想是比较交换,如果在过程中判断逻辑不够严谨,就会导致在一个线程将数据从A改成B,在另一个线程使用的时候,该线程又将数据改回了A,这样的时候对于另一个线程其实并没有感知到B值的存在。其实在整个过程中这个值是被修改过的。这种情况对于运算依赖比较大的场景影响比较大。解决的思路就是引入版本机制。

相关文章:

深入理解synchronized的原理是什么

对象头锁机制原则 Synchronized 的原理是什么 Synchronized 是由JVM实现的一种实现互斥同步的实现方式。如果查看synchronized关键字修饰的字节码,会发现在编译器生成了monitorenter和monitorexit两个字节码指令。   这两个指令的意思就是在虚拟机执行到monitore…...

Electron32-Vue3OS桌面管理os模板|vite5+electron32+arco后台os系统

原创新作electron32.xvue3arco.design仿ipad/windows桌面os系统。 基于最新跨平台技术Electron32、Vite5、Vue3 setup、Pinia2、Arco-Design、Echarts、Sortablejs实战开发桌面版osx管理系统。内置ipad/windows两种桌面风格模板、动态json配置桌面图标、自研栅格拖拽布局模板。…...

c++ 定义函数

在C中,定义函数是一个基本的编程概念。函数是执行特定任务的一段代码,可以接受参数并返回值。下面是关于如何定义和使用函数的详细介绍。 1. 函数的基本结构 函数的基本结构包括以下几个部分: 返回类型:表示函数返回值的类型。…...

【深度学习 计算机视觉】计算机视觉工程师所需的和有帮助的基本技能

计算机视觉工程师通常需要具备一系列的技术和非技术技能,以下是一些基本技能和知识领域,它们对于在这一领域取得成功非常有帮助: 技术技能 编程能力: 熟练掌握至少一种编程语言,如Python、C或Java。熟悉数据结构和算…...

【CSS】如何写渐变色文字并且有打光效果

效果如上,其实核心除了渐变色文字的设置 background: linear-gradient(270deg, #d2a742 94%, #f6e2a7 25%, #d5ab4a 48%, #f6e2a7 82%, #d1a641 4%);color: #e8bb2c;background-clip: text;color: transparent;还有就是打光效果,原理其实就是两块遮罩&am…...

Android 14(API 级别 34)中,DexClassLoader 不再支持可写 dex/jar 文件

Android 14(API 级别 34)中,DexClassLoader 不再支持从可写文件加载 dex/jar 文件。这意味着从Android 14开始,你不能再使用 DexClassLoader 来动态加载位于内部存储中的dex/jar文件,除非这些文件被设置为只读。 解决…...

Linux -动静态库

文章目录 1.文件系统1.1 inode1.2 硬链接定义特点使用方法 1.3软链接定义特点使用方法 2.动态库和静态库2.1动态库2.11定义与特点2.12使用方法 2.2 静态库2.21定义与特点2.22 使用方法 2.3示例2.31编写库代码2.32编译生成动态库2.33 编译生成静态库 2.4总结 1.文件系统 我们使…...

原点安全荣获“AutoSec Awards 安全之星”优秀汽车数据安全合规方案奖

9月3日,「AutoSec 2024第八届中国汽车网络安全周暨第五届智能汽车数据安全展」在上海盛大开幕。本届大会由谈思实验室和谈思汽车主办、上海市车联网协会联合主办,以汽车“网络数据安全、软件安全、功能安全”为主题,汇聚了国内外的技术专家、…...

2024前端面试题分享

前言 最近忙着面试很久没有更新文章了,分享一下我收集的前端面经,当然题目仅供参考(乞求秋招offer) 面试题 响应式布局 ---根据用户的的窗口变化而变化的布局方式 react 的hooks ---官方提供的钩子和自定义的钩子&#xf…...

数学基础 -- 线性代数之正交矩阵

正交矩阵 正交矩阵是线性代数中的一个重要概念,具有许多优良的性质,在数值计算、线性变换、信号处理等领域有着广泛的应用。 1. 正交矩阵的定义 一个 n n n \times n nn 的方阵 Q Q Q 如果满足以下条件: Q T Q Q Q T I Q^T Q Q Q^T …...

PostgreSQL 17即将发布,新功能Top 3

按照计划,PostgreSQL 17 即将在 2024 年 9 月 26 日发布,目前已经发布了第一个 RC 版本,新版本的功能增强可以参考 Release Notes。 本文给大家分享其中 3 个重大的新增功能。 MERGE 语句增强 MERGE 语句是 PostgreSQL 15 增加的一个新功能…...

心觉:别再做单线程的打工人!换个思路突破

Hi,我是心觉,与你一起玩转潜意识、脑波音乐和吸引力法则,轻松搞定人生挑战,实现心中梦想! 挑战日更写作161/1000(完整记录在下面) 公门洞开纳百川 众心逐梦越千山 号召引领潜力绽 心觉潜意识无间 想让财富翻个2倍…...

深度学习-用神经网络NN实现足球大小球数据分析软件

文章目录 前言一、 数据收集1.1特征数据收集代码实例 二、数据预处理清洗数据特征工程: 三、特征提取四、模型构建五、模型训练与评估总结 前言 预测足球比赛走地大小球(即比赛过程中进球总数是否超过某个预设值)的深度学习模型是一个复杂但有…...

linux 9系统分区扩容

1.可以看到我的是9.2的系统,系统分区:/dev/mapper/rl-root 83G 8.0G 75G 10% / 2.接下来,我们新增一块新的硬盘,而不是直接对这个硬盘的基础上再扩容。 关机,加30G硬盘,再开机 fdisk -l fdisk /dev/…...

Solidity初体验

一、概念知识 什么是智能合约? 智能合约是仅在满足特定条件时才在区块链上部署和执行的功能,无需任何第三方参与。 由于智能合约本质上是不可变的和分布式的,因此它们在编写和部署后无法修改或更新。此外,分布式的意义在于任何…...

大模型笔记01--基于ollama和open-webui快速部署chatgpt

大模型笔记01--基于ollama和open-webui快速部署chatgpt 介绍部署&测试安装ollama运行open-webui测试 注意事项说明 介绍 近年来AI大模型得到快速发展,各种大模型如雨后春笋一样涌出,逐步融入各行各业。与之相关的各类开源大模型系统工具也得到了快速…...

html前段小知识点

1. 什么是HTML? 超文本标记语言是一种 用于创建网页的标准标记语言 HTML 文档包含了HTML 标签及文本内容 也叫文档1.什么是css? CSS (层叠样式表),是一种用来为结构化文档添加样式的计算机语言,CSS 文件扩展名为 .css。 可以设…...

AD7606工作原理以及FPGA控制验证(串行和并行模式)

文章目录 一、AD7606介绍二、AD7606采集原理2.1 AD7606功能框图2.2 AD7606管脚说明 三、AD7606并行模式时序分析以及实现3.1 并行模式时序图3.2 并行模式时序要求3.3 代码编写3.4 仿真观察 四、AD7606串行模式时序分析以及实现4.1 串行模式时序图4.2 串行模式时序要求4.3 代码编…...

如何查看Pod的Container资源占用情况

云原生学习路线导航页(持续更新中) 方法一:直接查看pod的资源占用 kubectl top pods ${pod-name} -n ${ns} 方法二:通过运行的进程,查看pod的某个容器资源占用 1.找到pod所在node容器号:kubectl descri…...

WordPress上可以内容替换的插件

插件下载地址:WordPress内容替换插件 – 果果开发 类型 替换的类型:文章、自定义文章类型、分类、标签、媒体库、页面、评论、数据库表,不同的类型可以替换不同的字段。 替换字段 替换的字段,哪些字段内容需要替换。除了数据库…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂&#xff…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...