Java中synchronized锁的深入理解
作者:舒一笑 发布时间:2023-08-18 01:36:55
使用范围
synchronized使用上用于同步方法或者同步代码块
在锁实现上是基于对象去实现
使用中用于对static修饰的便是class类锁
使用中用于对非static修饰的便是当前对象锁
synchronized的优化
在jdk1.6中对synchronized做了相关的优化
锁消除
在synchronized修饰的代码块中,要是不涉及操作临界资源的情况,即便你写了synchronized修饰,也不会出发锁机制
锁膨胀
在一个循环中频繁的出现锁资源的获取与释放操作,会带来资源的消耗,于是便会将锁的范围扩大到循环的外边,避免频繁的竞争和获取锁资源而导致的资源消耗
public void method(){
for (int i = 0; i < Integer.MAX_VALUE; i++) {
synchronized ("") {
// 业务代码
}
}
}
锁升级
ReentrantLock中是基于乐观锁的CAS获取线程资源。资源拿不到的情况下才会挂起线程。synchronized在jdk1.6之间完全获取不到锁的情况下立即挂起线程,但是在1.6之后进行了锁的升级与优化。
无锁、匿名偏向:当前对象没有作为锁的存在
偏向锁:当前锁资源,只有一个线程频繁的获取和释放锁,那么只有该线程获取锁是判断是否是同一个线程,如果是线程资源拿走。如果线程不是当前自己的线程,则采用基于CAS的方式,尝试将偏向锁指向当前线程。如果获取不到则触发锁升级为轻量级锁,也就意味着发生了锁竞争的情况。
轻量级锁:使用自旋锁的方式频繁的采用CAS的方式获取锁资源。这里采用的自适应自旋锁(JVM更具上次的自旋结果来进行判断本次的自旋时间长短)。如果成功获取锁资源,资源取走。如果获取锁资源失败,锁升级。
重量级锁:最为传统的synchronized实现方式。拿不到锁资源之间挂起线程,然后进行用户态和内核态的不断切换。。。
synchronized锁的实现原理
synchronized锁是基于对象来进行实现的
关于MarkWord的内容展开示意图
从图中可以看出通过锁的标志位来进行区分锁的不同状态
synchronized锁升级的过程演示
使用之前需要导入一个依赖
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.9</version>
</dependency>
锁在默认情况下,开启了偏向锁的延迟
原因是因为在偏向锁升级为轻量级锁的时候会涉及到偏向锁的撤销,需要等到一个安全点(STW),才能完成对偏向锁的撤销,所以在并发的情况下就可以选择不开启偏向锁,或者设置偏向锁延迟开启
在JVM启动时会大量加载.class文件到内存,该操作会涉及synchronized使用,为了避免出现偏向锁撤销的操作。在启动初期,有一个延迟5s开启偏向锁的操作。
要是正常开启偏向锁,那么就不会出现无锁的状态,而是直接进入匿名偏向锁
变成了偏向锁
/**
* @author
* @date 2023/5/28
*/
public class Test15 {
public static void main(String[] args) throws InterruptedException {
Thread.sleep(5000);
Object o = new Object();
System.out.println(ClassLayout.parseInstance(o).toPrintable());
//thread 线程偏向锁
Thread thread = new Thread(()->{
synchronized (o){
System.out.println("thread线程 :"+ClassLayout.parseInstance(o).toPrintable());
}
});
thread.start();
// 轻量级锁 -> 重量级锁
synchronized (o){
System.out.println("main线程 :"+ClassLayout.parseInstance(o).toPrintable());
}
}
}
锁转换状态示意图
LockRecord和ObjectMonitor存储的内容示意图
来源:https://juejin.cn/post/7237996261214437431


猜你喜欢
- springboot和springmvc的区别spring boot 内嵌tomcat,Jetty和Undertow容器,可以直接运行起来,
- 目录1 简介2 项目整合2.1 JWT工具类2.2 JWT的过滤器2.3 Security的配置2.4 获取JWT的Controller3
- 在一些特定的 App 里,我们不希望手机横屏的时候,App 发生旋转,比如微信,企业微信都是这样的。代码可以这样设定:import '
- 发现问题需求很简单,大致就是要批量往数据库写数据,于是打算用Parallel并行的方式写入,希望能利用计算机多核特性加快程序执行速度。想的很
- ////////////////////////////
- 目录1 CyclicBarrier方法说明2 CyclicBarrier实例3 CyclicBarrier源码解析CyclicBarrier
- API参数:/**fileName: 临时文件的名字, 生成后的文件名字将会是【fileName + 随机数】suffix: 文件后缀,例如
- 昨天,我同学用Eclipse安装Aptana插件,她弄了一天都没安装起,最后找了我。 然后我也按照她的那个方法安装,结果一样,安装不成功!网
- 1.基本思路①.创建已加锁应用的数据库(字段:_id,packagename),如果应用已加锁,将加锁应用的包名维护到数据库中②.已加锁+未
- javax.persistence 介绍Spring Data JPA 采用约定大于配置的思想,默认了很多东西JPA是存储业务实体关联的实体
- 这篇文章主要介绍了Java判断主机是否能ping通代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要
- TabHost组件可以在界面中存放多个选项卡, 很多软件都使用了改组件进行设计。一、基础知识TabWidget : 该组件就是TabHost
- 在C# 的应用程序开发中, 我们经常要把UI线程和工作线程分开,防止界面停止响应, 同时我们又需要在工作线程中更新UI界面上的控件。但直接访
- 前言 OFD是国家标准版式文档格式,于2016年生效。OFD文档国家标准参见《电子文件存储与交换格式版式文档》。既然是国家标准,O
- 让按钮拥有返回键的功能很简单,在点击事件加上finish();就OK了。如:public void onClick(View v){fini
- 终端实现大文件上传一直都是比较难的技术,其中涉及到后端与前端的交互,稳定性和流量大小,而且实现原理每个人都有自己的想法,后端主流用的比较多的
- 前言今天看代码看到有牵扯到弱引用的东西,就先稍微补一补Java的四种引用类型吧。Java为引用类型专门定义了一个类Reference,它是引
- 背景出现了一次生产事故,事情是这样的,我们有一个项目,Java访问数据库的框架使用的是MyBatis。然后一个业务员在系统中查询了一个订单,
- 在Android中要让一个程序的界面始终保持一个方向,不随手机方向转动而变化的办法: 只要在AndroidManifest.xml里面配置一
- using System;using System.Collections.Generic;using System.ComponentMo