synchronized原理

本文详细介绍了Java中`synchronized`的关键字用法、实现原理,包括synchronized代码块和方法的区别,以及轻量级锁、重量级锁和偏向锁的状态转换过程。还探讨了JVM对`synchronized`的优化策略,如锁消除、锁粗化和锁膨胀。
摘要由CSDN通过智能技术生成

synchronized

synchronized的用法参考Java中使用同步关键字synchronized需要注意的问题 - @ 小浩 - 博客园

synchronized是非公平锁

synchronized实现原理

16_深入JVM源码-monitor竞争_哔哩哔哩_bilibili

synchronized与锁

 Java中的锁——Lock和synchronized - 夏末秋涼 - 博客园 (cnblogs.com)

原理总结

 1,synchronized代码块基于进入和退出monitor对象实现。代码编译后将monitorenter指令插入同步代码块的前面,monitorexit指令插入同步代码块的后面,发生异常时也会执行monitorexit指令

2,synchronized方法读取运行时常量池中方法的 ACC_SYNCHRONIZED 标志来隐式实现的

3,synchronized用的锁存储在对象头中的markword,markword中的锁标记指向的是monitor对象,

锁标记位(无锁01、轻量级锁00、重量级锁10、偏向锁01)

4,monitor对象有两个队列(EntryList、WaitSet)以及锁持有者Owner标记

synchronized的两种用法以及他们对应的字节码


package org.cc.lipiao.demo.synchronizedDemo;

public class SynchronizedDemo {

private static int sum;

    private Object obj = new Object();

    public static synchronized void add(){
sum++;
    }

public synchronized void minus(){
sum--;
    }

public void add2(){
synchronized (obj){
sum += 2;
        }
    }
}

 public static synchronized void add();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
    Code:
      stack=2, locals=0, args_size=0
         0: getstatic     #4                  // Field sum:I
         3: iconst_1
         4: iadd
         5: putstatic     #4                  // Field sum:I
         8: return
      LineNumberTable:
        line 17: 0
        line 18: 8

  public synchronized void minus();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_SYNCHRONIZED
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #4                  // Field sum:I
         3: iconst_1
         4: isub
         5: putstatic     #4                  // Field sum:I
         8: return
      LineNumberTable:
        line 21: 0
        line 22: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  this   Lorg/cc/lipiao/demo/synchronizedDemo/SynchronizedDemo;

  public void add2();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=1
         0: aload_0
         1: getfield      #3                  // Field obj:Ljava/lang/Object;
         4: dup
         5: astore_1
         6: monitorenter
         7: getstatic     #4                  // Field sum:I
        10: iconst_2
        11: iadd
        12: putstatic     #4                  // Field sum:I
        15: aload_1
        16: monitorexit
        17: goto          25
        20: astore_2
        21: aload_1
        22: monitorexit
        23: aload_2
        24: athrow
        25: return

可以看到当关键字用在方法时,字节码使用ACC_SYNCHRONIZED,当关键字用在代码块时,字节码使用monitorenter和monitorexit指令

java对象头和锁的状态

锁状态存储在对象头的mark word

总结下来就是:无锁时:0 01

偏向锁:线程id epoch 1 01

轻量级锁:指向栈中lock record的指针 00

重量级锁:指向互斥量的指针 10

锁状态

偏向锁

大多数情况下,锁总是由同一个线程多次获得

偏向锁的优势:减少同一线程获取锁的代价(线程进入或退出同步代码块时只需要检查偏向锁、锁标志位和线程ID即可)

在1.6之后是默认开启的,并且是在应用程序启动几秒之后开启

偏向锁处理流程:

1、第一次进入同步块并获取锁时,虚拟机将对象头偏向锁设为1,同时CAS操作(将线程ID记录到Mark Word中)

2、后面再有线程进入这个同步块时,比较当前线程的threadID和mark word中的threadID是否一致,如果一致那么无须使用CAS

3、如果threadID不一致,那么需要查看mark word中记录的线程1是否存活

4、如果没有存活,那么mark word被重置为无锁状态,当前线程可以竞争将其设置为偏向锁

5、如果存活,那么立刻查找线程1的栈帧信息,如果还是需要继续持有这个锁,那么暂停线程1,撤销偏向锁,升级为轻量级锁

6、如果线程1 不再使用该锁,那么将mark word设为无锁状态,重新偏向新的线程。

轻量级锁

1、线程1获取轻量级锁时会先把MarkWord复制一份到线程1的栈帧中的DisplacedMarkWord(用于存储锁记录的空间),然后使用CAS把对象头中的内容替换为DisplacedMarkWord的地址

2、如果在线程1复制对象头的同时(在线程1CAS之前),线程2也准备获取锁,复制了对象头到线程2的锁记录空间中,但是在线程2CAS的时候,发现线程1已经把对象头换了,线程2的CAS失败,那么线程2就尝试使用自旋锁来等待线程1释放锁。

3、如果自旋到了一定次数线程2还在自旋等待或者这时又有一个线程3过来竞争这个锁对象,那么这个时候轻量级锁就会膨胀为重量级锁。重量级锁把除了拥有锁的线程都阻塞,防止CPU空转。

重量级锁

TODO

JVM对synchronized的优化

锁消除:TODO

锁粗化:TODO

锁膨胀:无锁-》偏向锁-》轻量级锁-》重量级锁

平时写代码如何优化synchronized

减少synchronized的范围,减少synchronized的代码

降低synchronized的粒度:使用CurrentHashMap替代Hashtable等等

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值