【JavaEE多线程】synchronized原理篇

news2024/9/20 7:53:26

目录

一、synchronized的优化机制

1)无锁状态

2)偏向锁状态:非必要,不加锁

 3)轻量级锁

4)重量级锁:挂起等待

二、锁消除

三、锁粗化

锁的粒度 

锁粗化的好处


      在这一篇文章当中,我们也提到了synchronized的作用。

Java对于synchronized的初步认识_革凡成圣211的博客-CSDN博客synchronized,死锁,https://blog.csdn.net/weixin_56738054/article/details/128062475?spm=1001.2014.3001.5501       回顾一下,在synchronized当中,两个线程如果针对同一个对象加锁,如果一个线程可以获取到锁,另外一个线程就会进入阻塞等待的状态。

       关于synchronized锁的一些特性,在这一篇文章当中,已经提到了。
【JavaEE进阶】锁的特性_革凡成圣211的博客-CSDN博客Java锁的特性https://blog.csdn.net/weixin_56738054/article/details/128574608?spm=1001.2014.3001.5501

       下面,再回顾一下synchronized的几个特性:

        特性一、synchronized是一个非公平锁;

        特性二、synchronized是一个可重入锁;

        特性三、synchronized是一个悲观锁;

        特性四、synchronized是一个互斥锁,两个线程不可以同时占有一把锁;

        特性五、synchronized可以由一个轻量级锁转化为重量级锁


一、synchronized的优化机制

       以下四个过程:就是在线程进入synchronized代码块当中之后,加锁的过程,就可能会经历下面这几个阶段。        

synchronized(locker){

  //在这个内部,进行加锁的过程

}

synchronized内部其实还有一些优化机制,存在的目的就是为了让这个加锁的过程更加高效。

下面,将重点分析一下加锁的几个过程:

1)无锁状态

 不加锁,这种状态一般不会存在。如果真的存在,那么很有可能是被编译器把锁给优化掉了。


2)偏向锁状态:非必要,不加锁

       当进入synchronized代码块当中之后,首先会进入到偏向锁的状态;

       其实偏向锁,就是一个线程对对象尝试加锁的一种状态,并没有真正施加锁,而是先对于这个对象做一个标记。做标记这个过程,其实相比于真正加锁,还是轻量了不少的。

       如果整个使用锁的过程当中,都没有出现锁竞争,那么这个标记,就会在线程离开synchronized之后释放;

       如果另外一个线程同时也尝试对于同一个对象加锁,那么就会造成锁升级,转变为轻量级锁。

    


 3)轻量级锁

   对于synchronized,它的轻量级锁,是通过自旋锁的方式来实现的。

   对于自旋锁的解释,也已经在这一篇文章当中提到了:
【JavaEE进阶】锁的特性_革凡成圣211的博客-CSDN博客Java锁的特性https://blog.csdn.net/weixin_56738054/article/details/128574608?spm=1001.2014.3001.5501

       自旋锁虽然不会造成线程的阻塞等待,但是如果无法通过CAS获取到锁,就会一直在循环当中尝试获取锁。

       如果获取到锁的线程很快就释放锁了,那么也就意味着自旋是划算的。

       如果获取到锁的线程一直没有释放锁,那么这个自旋的过程是很消耗cpu资源的

       因此,当synchronized处于自旋锁的状态的时候,它的内部会有一个计数器,当计算的数量达到一定的数目之后,就停止自旋,升级为重量级锁


4)重量级锁:挂起等待

       重量级锁,会造成线程阻塞等待。这个过程,则是基于操作系统原生的API来实现的。

       这个时候,如果线程进行了重量级锁的加锁过程,那么获取不到锁的线程就会被操作系统调度离开CPU内核,被放入阻塞队列当,暂时不参与CPU的运算调度。

       重量级锁,因为涉及线程调度离开CPU,调度回到CPU的过程,相比起轻量级锁,会更

加消耗CPU的资源。

         目前JVM,只支持锁升级的操作,不支持锁降级的操作。 


二、锁消除

锁消除是发生在编译阶段的事件 

编译器的智能判定,看当前代码是否真的需要加锁。

如果不需要加锁 ,代码当中也加锁了,那么这个锁就会被编译器消除。


经典现象:对于StringBuffer,如果单线程环境使用,那么编译器就会把这个锁消除掉。


三、锁粗化

锁的粒度 

对于synchronized:它所包含的代码越多,粒度就越粗。包含的代码越少,粒度就越细。

在保证线程安全的情况下面,锁的粒度越细越好 

对于ConcurrentHashMap来说,它的put方法的粒度就比Hashtable的put方法的粒度细很多。


锁粗化的好处

       如果对于一些应用场景,两次加锁之间,间隙非常小。

       但是由于加锁、解锁的过程也是需要一定的开销的。那不如直接使用一把大锁搞定,就不再反复加锁、解锁了。

       这种变多把小锁一把大锁的现象,就被称为锁的粗化


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

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

相关文章

Python super()函数:调用父类的构造方法

Python 中子类会继承父类所有的类属性和类方法。严格来说,类的构造方法其实就是实例方法,因此毫无疑问,父类的构造方法,子类同样会继承。但我们知道,Python 是一门支持多继承的面向对象编程语言,如果子类继…

『Nonebot 插件编写教程』nonebot2处理消息的完整过程

文章目录前言捕获消息处理消息Bot机器人参数Event事件参数回复消息字符串与Message调用MessageSegment接口前言 前面已经有不止一篇博客教大家如何搭建nonebot2环境了大家可以去专栏查看,这篇博客并不会再次带大家来搭建nonebot2环境,而是着手与插件的编…

【微服务】Sentinel规则持久化

Sentinel 规则持久化 一、修改微服务 修改微服务&#xff0c;让其监听Nacos中的sentinel规则配置。 具体步骤如下&#xff1a; 1.引入依赖 在order-service中引入sentinel监听nacos的依赖&#xff1a; <dependency><groupId>com.alibaba.csp</groupId>…

数据结构实验三: 图的操作与实现

数据结构实验一:线性表,堆栈和队列实现 数据结构实验二 :二叉树的操作与实现 数据结构实验三: 图的操作与实现 数据结构实验四 : 查找和排序算法实现 文章目录一、实验目的&#xff1a;二、使用仪器、器材三、实验内容及原理1、教材P310实验题1&#xff1a;实现图的邻接矩阵和邻…

Springboot扩展点之BeanFactoryPostProcessor

Springboot扩展点之BeanFactoryPostProcessor1.功能特性BeanFactoryPostProcessor的执行是Spring Bean生命周期非常重要的一部分&#xff1b; BeanFactory级别的后置处理器&#xff0c;在Spring生命周期内&#xff0c;org.springframework.beans.factory.config.BeanFactoryPos…

【C语言】10题相关讲解+总结----有用的知识1

总结【C语言】10题&#xff0c;有兴趣的可以看看1.结构体与typedef联系2.结构体中涉及的操作符3.指针数组与数组指针4.数组首元素的作用5.喝汽水问题6.上三角矩阵判定7 矩阵相等判定8.VS调试技巧9.Debug与Release关系10.调整奇数偶数顺序11.有序序列合并1.结构体与typedef联系 …

开发互动直播应用很简单:声网 Android Demo保姆级运行教程

本文作者是来自声网开发者社区的用户“Xiaohua”。 前言 本人在参与《声网开发者漫游指南》期间&#xff0c;通过学习了解和学会跑通声网的实时互动Demo&#xff0c;但因为课程提供的demo是移动端和pc端的&#xff0c;很少接触过&#xff0c;所以只能花点时间学习一下才能运行…

如何屏蔽 iOS 软件自动更新,去除更新通知和标记

如何禁用 iPhone、iPad 软件自动更新。适用于 iOS、iPadOS 和 watchOS&#xff0c;即 iPhone、iPad 和 Apple Watch 通用。 请访问原文链接&#xff1a;https://sysin.org/blog/disable-ios-update/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&a…

WebAssembly编译之(4)-WASM编译进阶(多文件、多接口)

引言 上一节我们讲到如何用Emscripten将一个C编译陈wasm&#xff0c;并导出可供Javascirpt调用的接口&#xff0c;以及C导出类的函数接口、导出类的封装对象等。然而&#xff0c;编译的方式比较玛法&#xff0c;有没办法能更友好一点实现wasm的编译呢 WASM 相关文档&#xff1a…

【自学Docker】Docker diff命令

Docker diff命令 大纲 docker diff命令教程 docker diff 命令用于比较一个 Docker容器 不同版本提交的文件差异。该命令后面的 CONTAINER 可以是容器Id&#xff0c;或者是容器名。 docker diff命令会列出 3 种容器内文件状态变化&#xff08;A - Add, D - Delete, C - Chang…

Java-基础-3.容器

一&#xff1a;为什么会出现容器&#xff1f; 在之前的学习中&#xff0c;我们学习了变量和常量。都是一个字符或者字符串&#xff0c;数字的情况。但是在实际的生产中&#xff0c;我们一次会接受到很多类型不同&#xff0c;个数不同的数据。所以&#xff0c;为了方便我们后续…

红杉:2022企业数字化年度指南

省时查报告-专业、及时、全面的行研报告库省时查方案-专业、及时、全面的营销策划方案库【免费下载】2022年12月份热门报告盘点罗振宇2023年跨年演讲PPT原稿吴晓波2022年年终秀演讲PPT原稿2023年&#xff0c;如何科学制定年度规划&#xff1f;《底层逻辑》高清配图华为2021数字…

[基础语法] python语法之列表的基本操作

文章目录列表已发布列表的基本操作增删改查排序列表实例练习列表 已发布 python判断语句python循环语句python之列表list python 的数据格式主要有列表、字典、元组、集合。其中列表的使用最为广泛。 任何一种数据格式的使用都离不开增、删、改、查四个操作。列表除了这四个…

【Mysql第四期 运算符规则计算】

文章目录写在前面1.算数运算符2.比较运算符3.逻辑运算符4.位运算符5.运算符的优先级拓展&#xff1a;使用正则表达式查询写在前面 基本的运算符号在计算机编程领域都是相通的&#xff0c;会有自己的一些特定符号语言&#xff0c;就像是各地的普通话一样&#xff0c;尽管语音描…

剑指 Offer II 004只出现一次的数字

给你一个整数数组 nums &#xff0c;除某个元素仅出现 一次 外&#xff0c;其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。 示例 1&#xff1a; 输入&#xff1a;nums [2,2,3,2] 输出&#xff1a;3 示例 2&#xff1a; 输入&#xff1a;nums [0,1,0,…

Linux中Vi编辑器和Vim编辑器

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;Java案例分…

Docker常用命令总结

基础命令 1.启动docker systemctl start docker 2.关闭docker systemctl stop docker 3.设置docker为自启动 systemctl enable --now docker 4.重启docker systemctl restart docker 3.查看docker版本信息 docker version 4.查看docker详细信息 docker info Clien…

Spring定时器超过30分钟问题

目前需要定时器做一个定时扫描任务的功能&#xff0c;原先都是定时在半个小时&#xff0c;程序跑起来也没事。但是最近公司要求定时时间加长到45分钟&#xff0c;而调整完配置完后发现&#xff0c;程序是在45分钟和整点进行的扫描。 下面是我做的示例时间缩短为45秒 spring。x…

守护进程编程流程及代码实现

概念不做阐述&#xff0c;本文主要内容为守护进程编程部分的知识说明 守护进程的编程流程&#xff1a; 1.fork退出父进程&#xff0c;保证留下的子进程是组员进程 2.利用setsid()创建新会话&#xff0c;把子进程挪到新的会话中 //获取会话是getsid() 3.fork退出父进程&#x…

完成基于Servlet的对user表的增删改查

基于Servlet的增删改查 1.开发环境 IDEAJDK1.8Tomcat8.5Mysql 8.0.12 2.数据库 2.1表创建 2.2表数据 3.JavaWeb代码 3.1目录结构 3.2util包下代码 JdbcUtil完成对数据库的连接和资源释放 JsonResult对返回前端资源的封装 JdbcUtil代码&#xff1a; /* 数据库连接板帮助类 …