Java中synchronized锁的深入理解

作者:舒一笑 时间:2023-08-18 01:36:55 

使用范围

  • synchronized使用上用于同步方法或者同步代码块

  • 在锁实现上是基于对象去实现

  • 使用中用于对static修饰的便是class类锁

  • 使用中用于对非static修饰的便是当前对象锁

Java中synchronized锁的深入理解

synchronized的优化

  • 在jdk1.6中对synchronized做了相关的优化

锁消除

  • 在synchronized修饰的代码块中,要是不涉及操作临界资源的情况,即便你写了synchronized修饰,也不会出发锁机制

Java中synchronized锁的深入理解

锁膨胀

  • 在一个循环中频繁的出现锁资源的获取与释放操作,会带来资源的消耗,于是便会将锁的范围扩大到循环的外边,避免频繁的竞争和获取锁资源而导致的资源消耗

public void method(){
       for (int i = 0; i < Integer.MAX_VALUE; i++) {
           synchronized ("") {
               // 业务代码
           }
       }
   }

Java中synchronized锁的深入理解

Java中synchronized锁的深入理解

锁升级

  • ReentrantLock中是基于乐观锁的CAS获取线程资源。资源拿不到的情况下才会挂起线程。synchronized在jdk1.6之间完全获取不到锁的情况下立即挂起线程,但是在1.6之后进行了锁的升级与优化。

  • 无锁、匿名偏向:当前对象没有作为锁的存在

  • 偏向锁:当前锁资源,只有一个线程频繁的获取和释放锁,那么只有该线程获取锁是判断是否是同一个线程,如果是线程资源拿走。如果线程不是当前自己的线程,则采用基于CAS的方式,尝试将偏向锁指向当前线程。如果获取不到则触发锁升级为轻量级锁,也就意味着发生了锁竞争的情况。

  • 轻量级锁:使用自旋锁的方式频繁的采用CAS的方式获取锁资源。这里采用的自适应自旋锁(JVM更具上次的自旋结果来进行判断本次的自旋时间长短)。如果成功获取锁资源,资源取走。如果获取锁资源失败,锁升级。

  • 重量级锁:最为传统的synchronized实现方式。拿不到锁资源之间挂起线程,然后进行用户态和内核态的不断切换。。。

synchronized锁的实现原理

  • synchronized锁是基于对象来进行实现的

Java中synchronized锁的深入理解

  • 关于MarkWord的内容展开示意图

Java中synchronized锁的深入理解

  • 从图中可以看出通过锁的标志位来进行区分锁的不同状态

synchronized锁升级的过程演示

  • 使用之前需要导入一个依赖

<dependency>
           <groupId>org.openjdk.jol</groupId>
           <artifactId>jol-core</artifactId>
           <version>0.9</version>
       </dependency>

Java中synchronized锁的深入理解

  • 锁在默认情况下,开启了偏向锁的延迟

  • 原因是因为在偏向锁升级为轻量级锁的时候会涉及到偏向锁的撤销,需要等到一个安全点(STW),才能完成对偏向锁的撤销,所以在并发的情况下就可以选择不开启偏向锁,或者设置偏向锁延迟开启

  • 在JVM启动时会大量加载.class文件到内存,该操作会涉及synchronized使用,为了避免出现偏向锁撤销的操作。在启动初期,有一个延迟5s开启偏向锁的操作。

  • 要是正常开启偏向锁,那么就不会出现无锁的状态,而是直接进入匿名偏向锁

Java中synchronized锁的深入理解

  • 变成了偏向锁

Java中synchronized锁的深入理解

/**
* @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());
       }
   }
}

Java中synchronized锁的深入理解

锁转换状态示意图

Java中synchronized锁的深入理解

LockRecord和ObjectMonitor存储的内容示意图

Java中synchronized锁的深入理解

来源:https://juejin.cn/post/7237996261214437431

标签:Java,Synchronized,锁
0
投稿

猜你喜欢

  • C#中的委托介绍

    2023-07-27 13:26:23
  • Mybatis执行流程、缓存原理及相关面试题汇总

    2022-10-15 23:30:28
  • C#快速实现IList非泛型类接口的自定义类作为数据源

    2022-10-09 20:28:24
  • Intellij IDEA 2017新特性之Spring Boot相关特征介绍

    2023-06-22 15:13:02
  • Android仿QQ微信实时监测网络状态

    2022-10-10 06:48:52
  • 详解SpringBoot定制@ResponseBody注解返回的Json格式

    2023-07-26 13:47:02
  • winform 实现选择文件和选择文件夹对话框的简单实例

    2022-02-21 07:05:12
  • c#(Socket)异步套接字代码示例

    2021-06-28 11:06:03
  • Android开发使用自定义View将圆角矩形绘制在Canvas上的方法

    2021-06-08 01:03:17
  • SpringMVC+Mybatis实现的Mysql分页数据查询的示例

    2023-11-24 20:53:33
  • Spring Cloud基于zuul实现网关过程解析

    2021-09-11 06:52:19
  • Springboot中Aspect切面的实现方式(以记录日志为例)

    2022-09-15 20:58:25
  • 基于@GetMapping注解携带参数的方式

    2023-01-26 20:49:32
  • 浅谈Android的Lifecycle源码分析

    2023-03-08 21:42:04
  • C#邮件定时群发工具Atilia用法实例

    2022-06-13 11:50:24
  • Java Socket编程实例(一)- TCP基本使用

    2023-11-11 08:42:50
  • C#采用FileSystemWatcher实现监视磁盘文件变更的方法

    2023-12-10 02:52:49
  • Java实现InputStream的任意拷贝方式

    2022-04-08 10:11:32
  • Unity工具类之生成文本验证码

    2021-06-21 03:38:42
  • C#基于socket模拟http请求的方法

    2022-09-12 09:55:11
  • asp之家 软件编程 m.aspxhome.com