sychronize的实现原理是怎么样的?

简介: 基础


public class SyncTest {
    public void syncBlock(){
        synchronized (this){
            System.out.println("hello block");
        }
    }
    public synchronized void syncMethod(){
        System.out.println("hello method");
    }
}点击复制代码复制出错复制成功

当SyncTest.java被编译成class文件的时候,synchronized关键字和synchronized方法的字节码略有不同,我们可以用javap -v 命令查看class文件对应的JVM字节码信息,部分信息如下:

{
  public void syncBlock();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=1
         0: aload_0
         1: dup
         2: astore_1
         3: monitorenter                       // monitorenter指令进入同步块
         4: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         7: ldc           #3                  // String hello block
         9: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        12: aload_1
        13: monitorexit                          // monitorexit指令退出同步块
        14: goto          22
        17: astore_2
        18: aload_1
        19: monitorexit                          // monitorexit指令退出同步块
        20: aload_2
        21: athrow
        22: return
      Exception table:
         from    to  target type
             4    14    17   any
            17    20    17   any
  public synchronized void syncMethod();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_SYNCHRONIZED      //添加了ACC_SYNCHRONIZED标记
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #5                  // String hello method
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
}点击复制代码复制出错复制成功

对于synchronized关键字而言,javac在编译时,会生成对应的monitorentermonitorexit指令分别对应synchronized同步块的进入和退出,有两个monitorexit指令的原因是为了保证抛异常的情况下也能释放锁,所以javac为同步代码块添加了一个隐式的try-finally,在finally中会调用monitorexit命令释放锁。

而对于synchronized方法而言,javac为其生成了一个ACC_SYNCHRONIZED关键字,在JVM进行方法调用时,发现调用的方法被ACC_SYNCHRONIZED修饰,则会先尝试获得锁。

synchronized锁执行流程图

这是网上看到的一个流程图:

就是Java对象的内存布局其实由对象头+实例数据+对齐填充三部分组成,而对象头主要包含Mark Word+指向对象所属的类的指针组成。Mark Word主要用于存储对象自身的运行时数据,哈希码,GC分代年龄,锁标志等。

下面就是Mark Word的数据映射表

相关文章
|
存储 Java
HashMap与LinkedHashMap类型集合
【8月更文挑战第4天】`HashMap` 是基于哈希表实现的键值对存储结构,提供快速的查找、插入和删除操作,但不保证元素顺序。适用于不关心顺序且需高效操作的场景。 `LinkedHashMap` 继承自 `HashMap`,保持了元素的插入或访问顺序。适合需要按特定顺序遍历元素的应用,如按添加顺序显示购物车商品。其操作效率与 `HashMap` 相近。
147 1
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的一次性环保餐具销售系统的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的一次性环保餐具销售系统的详细设计和实现(源码+lw+部署文档+讲解等)
|
弹性计算 数据安全/隐私保护 计算机视觉
|
消息中间件 存储 运维
【深入浅出之透析RocketMQ原理及实战指南】RocketMQ学习入门指南 | ​​RocketMQ物理和逻辑架构结构精讲​
【深入浅出之透析RocketMQ原理及实战指南】RocketMQ学习入门指南 | ​​RocketMQ物理和逻辑架构结构精讲​
398 0
【深入浅出之透析RocketMQ原理及实战指南】RocketMQ学习入门指南 | ​​RocketMQ物理和逻辑架构结构精讲​
|
开发者 Python
Flask 安装 | 学习笔记
快速学习 Flask 安装
229 0
|
前端开发
静态页如何更好地展示相关文章
静态页如何更好地展示相关文章
165 0
|
Android开发 计算机视觉 数据格式
|
SQL Java 数据库连接
JDK6笔记(5)----JDBC4(3)
JDK6笔记(5)----JDBC4(3) 1、预准备语句的IN参数的pitfall 当你用setter方法向IN参数传递值时要注意一些问题。 不管在任何时候,设置参数并执行预准备语句对象,JDBC驱动器会把Java类型转换成DBMS所能理解的JDBC类型。
875 0
|
2天前
|
弹性计算 人工智能 安全
云上十五年——「弹性计算十五周年」系列客户故事(第二期)
阿里云弹性计算十五年深耕,以第九代ECS g9i实例引领算力革新。携手海尔三翼鸟、小鹏汽车、微帧科技等企业,实现性能跃升与成本优化,赋能AI、物联网、智能驾驶等前沿场景,共绘云端增长新图景。