线程中并发安全问题(Sychronized关键字的底层原理)

news2024/12/23 3:50:06

线程中并发安全问题

Sychronized关键字的底层原理

sychronized对象锁采用互斥方式让同一时刻至多只有一个线程能持有对象锁,其他线程想获取这个对象锁只能被阻塞。

Monitor

Sychronized的底层实现Monitor。
在这里插入图片描述在这里插入图片描述

  • WaitSet:关联调用了wait方法的线程,用于存储处于等待状态的线程。
  • EntryList:关联了没有获得的线程,用于存储处于Blocked状态的线程。
  • Owner:存储当前获取锁的线程,只有一个线程可以获取到(如果Owner为NULL则表示线程可以获取否则就在EntryList中等待,等到当前线程执行完毕,EntryList中的其他线程对锁进行争抢。

Monitor是一个重量级锁(牵扯到一个新的概念:锁升级)

​ monitor实现锁里面涉及到了内核态和用户态的切换,进程的上下文切换成本较高,性能较低。

​ 所以再JDK1.6之后引入了两种新型的锁机制:轻量级锁偏向锁,他们的引入分别解决了同步块中代码不存在竞争,在不同线程交替执行同步代码块中代码不存在竞争这两种因使用传统锁机制产生的性能消耗问题的情况。

所以对象锁是如何关联Monitor的?

对象的内存结构

​ 在HotSpot虚拟机中,对象在内存中存储的分布可分为3个区域:对象头(Header)实例数据(Instance Data),对其填充。

在这里插入图片描述
在这里插入图片描述

MarkWord

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oIHjZVN0-1689425757766)(D:\线程中并发安全问题\QQ截图20230715201033.png)]

  • hashcode:25位的对象标识Hash码
  • age:对象分代年龄占4位
  • biased_lock:偏向锁标识,占1位 ,0表示没有开始偏向锁,1表示开启了偏向锁
  • thread:持有偏向锁的线程ID,占23位
  • epoch:偏向时间戳,占2位
  • ptr_to_lock_record:轻量级锁状态下,指向栈中锁记录的指针,占30位
  • ptr_to_heavyweight_monitor:重量级锁状态下,指向对象监视器Monitor的指针,占30位

Monitor重量级锁

​ 每个对象都可以关联一个Monitor,如果使用sychronized给对象上锁(重量级)后,该对象头中MarkWord中就被修改为指向Monitor对象的指针。

轻量级锁

​ 在很多情况下,Java中的同步代码块并不会被竞争使用,可能会有多个线程交替执行同步块中的代码,这样的情况没必要使用重量级锁,因此Jvm引入了轻量级锁概念。

在这里插入图片描述

​ 当代码执行完成,如果锁记录(Lock Record)为NULL就直接将该锁记录清除,若是不为NULL(也就是原本锁对象CAS过来的MarkWord)此时再进行一次CAS操作将原本的MarkWord交换回来,就代表着解锁成功。

总结

轻量级锁加锁流程:

  • 在线程栈中创建出一条LockRecord锁记录,将其指向锁对象。
  • 通过CAS指令,将LockRecord地址存储到锁对象对象头MarkWord中,若对象处于无锁状态,则修改成功,表示当前线程已经获取到了轻量级锁。
  • 若是当前线程已经持有该锁,代表这是一次锁重入,设置一个新的LockRecard到线程栈中,设置其第一部分为null,起到一个锁重入计数器的功能。
  • 如果CAS修改失败,说明发生了锁竞争,要将其膨胀为重量级锁。

轻量级锁解锁过程:

  • 遍历线程栈找到所有的obj字段(也就是Lock Record地址)为当前锁对象的锁记录。
  • 若是lock record的Markword为null代表着是一次重入,直接清除当前锁记录。
  • 若是不为null则利用cas指令将对象头中的MarkWord交换回来,恢复为无锁状态,若是失败则膨胀为重量级锁。

偏向锁

​ 轻量级锁在没有竞争时,每次重入锁都要进行CAS操作,java6中引入了偏向锁来进一步的优化:只有第一次使用CAS将线程ID设置到对象的MarkWord中,之后每次重入只要发现这个线程ID是自己的就表示没有竞争,不用CAS,以后只要不发生竞争,这个锁对象就归该线程所有。

总结

​ Java中的Sychronized分为偏向锁轻量级锁重量级锁三种形式,分别对应着锁只被一个线程持有不同线程交替持有多线程竞争锁

  • 重量级锁:底层使用Monitor实现,里面设计了用户态和内核态的切换,上下文切换,成本高性能低。
  • 轻量级锁:线程的加锁时间是分开的,也就是没有竞争,可以使用轻量级锁来优化,轻量级锁修改对象头的锁标志,相对重量级锁性能提升,每次修改都是CAS保证原子性
  • 偏向锁:一段时间内都是同一个线程持有锁,可以使用偏向锁,在第一次获取锁后,只会一次CAS操作,之后该线程获取锁,只需要判断线程ID是否正确,而不是开销较大的CAS操作。

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

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

相关文章

DVDNET A FAST NETWORK FOR DEEP VIDEO DENOISING

DVDNET: A FAST NETWORK FOR DEEP VIDEO DENOISING https://ieeexplore.ieee.org/document/8803136 摘要 现有的最先进视频去噪算法是基于补丁的方法,以往的基于NN的算在其性能上无法与其媲美。但是本文提出NN的视频去噪算法性能要好: 其相比于基于补丁…

【板栗糖GIS】——buzz字幕软件的安装和使用

【板栗糖GIS】——buzz字幕软件的安装和使用 1. 下载buzz软件 链接如下: 下载软件包,我已经准备好资源,只是审核还未通过,过两天会加上,忘记补充链接可以私信我 2. 双击安装 直接下一步下一步 3. 使用方法介绍 运…

并发事务会有哪些问题?

并发事务会有哪些问题? 多个事务并发的执行一定会出现相互争夺资源的问题。那么问题具体有哪些呢? 脏写(丢失修改)脏读不可重复读幻读 以上这四个问题就是我们需要知道的。但是脏写,由于mysql最低的隔离级别都能避免…

gradle的下载、解压、环境变量配置以及命令行基本用法

父目录 Android 开发入门 - wuyujin1997 文章目录 Intro下载解压配置环境变量环境变量测试 命令行命令行基本用法命令行更多用法 Intro 关于Java项目的依赖、编译流程等管理,有三代的解决方案。 AntMavenGradle 可以想像这三代工具必定是各有特定,但整…

【算法 -- LeetCode】(020) 有效的括号

1、题目 给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个…

javaagent简单理解

1. javajaent是什么 javaagent可以理解为是一个插件,需要有一个jvm进程才能运行。例如arthas这个工具就是用到了javaagent。 2. 如何使用 1. 一种调用方式:java -javaagent:path[参数参数值] 2. 方法签名 public static void premain(String args, I…

从零玩转系列之SpringBoot3-核心原理

一、简介 1.前置知识 ● Java17 ● Spring、SpringMVC、MyBatis ● Maven、IDEA 2.环境要求 环境&工具版本(or later)SpringBoot3.1.xIDEA2023.xJava17Maven3.5Tomcat10.0Servlet5.0GraalVM Community22.3Native Build Tools0.9.19 二、SpringBoot3-核心原理 1.事件和监听器…

【Hippo4j监控Web容器Tomcat线程池】

🚀 线程池管理工具-Hippo4j 🚀 🌲 AI工具、AI绘图、AI专栏 🍀 🌲 如果你想学到最前沿、最火爆的技术,赶快加入吧✨ 🌲 作者简介:硕风和炜,CSDN-Java领域优质创作者&#…

知识整合:Web页面请求的历程

Web页面请求的历程 内部涉及知识:一、准备:DHCP、UDP、IP 和以太网二、仍在准备:DNS和ARP三、仍在准备:域内路由选择到DNS服务器四、Web客户-服务器交互:TCP和HTTP五、HTTP请求响应格式Requests部分Responses 部分 下载一个Web页面…

2023.7.15

同余最短路 P3403 跳楼机 题意:给定h高的楼层,起始位置在第一层,可以选择操作向上移动x层或y层或z层,回到第一层 求可以到达的楼层数 思路:转化题意为求axbyczk(k在[1,h],x,y,z为正整数,有多少k满足条件&am…

基础IO

1.C的文件接口 "r" - 只读模式,打开文件用于读取,文件必须存在。 "w" - 写模式,打开文件用于写入,如果文件已存在则清空文件内容,如果文件不存在则创建新文件。 "a" - 追加模式&#…

手把手搭建mybatis入门程序

目录 准备数据库表 搭建工程 引入日志框架lockback SqlSessionUtil工具类封装 准备数据库表 CREATE TABLE t_car (id bigint NOT NULL AUTO_INCREMENT COMMENT 主键,car_num varchar(100) DEFAULT NULL COMMENT 汽车编号,brand varchar(100) DEFAULT NULL COMMENT 品牌,gui…

阿里云2核4G服务器能搭建几个网站?性能如何?

2核4G服务器能安装多少个网站?2核4g配置能承载多少个网站?一台2核4G服务器可以安装多少个网站?阿腾云2核4G5M带宽服务器目前安装了14个网站,从技术角度是没有限制的,只要云服务器性能够用,想安装几个网站就…

Java正则表达式校验某个字符串是否是合格的email

Java正则表达式校验某个字符串是否是合格的email 可以借助正则表达式校验某个字符串是否是合规的电子邮箱。对于邮箱的正则表达式有严格的模式,如:^[a-zA-Z0-9_&*-](?:\\.[a-zA-Z0-9_&*-])*(?:[a-zA-Z0-9-]\\.)[a-zA-Z]{2,7}$ 对应的Java实现…

Verilog基础之十六、RAM实现

目录 一、前言 二、工程设计 2.1 RAM IP核使用 2.2 设计代码 2.3 仿真代码 2.4 综合结果 2.5 仿真结果 一、前言 工程设计中除逻辑计算单元外,存储单元也是不可获取的部分,RAM(Random Access Memory)随机存取存储器即可以写入数据,也可…

Spring Cloud Gateway下的GC停顿排查之旅

01 背景 在微服务架构体系流行的当下,Spring Cloud全家桶已经是大多数团队的首选,我们也不例外,并且选择了Spring Cloud Gateway作为了业务网关,进行了一些通用能力的开发,如鉴权、路由等等。作为一个成熟的框架&#…

非线性弹簧摆的仿真(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

matplotlib定制绘图的线型、标记类型

文章目录 折线图参数列表实战演示特征字符串 折线图 折线图是科研绘图中最常见的一种图形, 表现的是数据的变化情况 import numpy as np import matplotlib.pyplot as pltx np.linspace(0,10,100) y np.sin(x) plt.plot(x,y) plt.show()参数列表 尽管绘图逻辑十…

Tensorflow-gpu保姆级安装教程(Win11, Anaconda3,Python3.9)

Tensorflow-gpu 保姆级安装教程(Win11, Anaconda3,Python3.9) 前言Tensorflow-gpu版本安装的准备工作(一)、查看电脑的显卡:(二) 、Anaconda的安装(三)、cuda下载和安装(四)、cudnn下载安装(五)、配置环境变量(六)、创建 tensorfl…

idea生成类关系图Diagrams

打开或选择该类,此处我以FutureTask类为例 在打开的该类内容内随意地方右键(或选中该类文件)》选择Diagrams》Show Diagrams》Java Classes此时就可以看到该类的关系图了