Synchronized 锁升级过程

本文详细探讨了Java对象锁的原理,包括synchronized的作用、对象结构(对象头、对象体和对其字节)、锁升级过程(无锁、偏向锁、轻量级锁到重量级锁的转变)。重点讲解了线程间的竞争和锁状态转换,帮助理解Java并发控制机制。
摘要由CSDN通过智能技术生成

一.Synchronized作用

修饰静态方法:锁住当前 class,作用于该 class 的所有实例
修饰非静态方法:只会锁住当前 class 的实例
修饰代码块:该方法接受一个对象作为参数,锁住的即该对象

二.Java对象结构

2.1对象头
mark Word:主要用于存储自身运行时数据,主要表示当前Java对象的线程锁状态(无锁,偏向锁,轻量级锁,重量级锁)以及GC的标志;
Class Pointer:是指针,指向方法区中该 class 的对象,JVM 通过此字段来判断当前对象是哪个类的实例;
数组长度:当且仅当对象是数组时才会有该字段;

2.2对象体:包含了当前对象的字段和值

2.3对其字节:用于填充的字节,其目的是为了保证对象所占用的内存大小为 8 的倍数

三.锁升级过程

3.1无锁
当线程运行,没有其他线程来竞争。锁的标志位为01

3.2 偏向锁
一直只被线程A访问,没有其他线程来竞争,标志位为01, biased_lock标志来区分,1 为启用偏向锁

3.3 轻量级锁
一旦有第二个线程参与竞争,立即膨胀为轻量级锁,企图抢占的线程一开始会使用自旋的方式尝试获取锁,1.7是普通自旋,设定一个最大的自旋次数,默认是10 ,1.7之后是自适应自旋,自旋获取到锁,则自旋的次数则会增加,自旋获取不到锁次数则会减少;

3.4 重量级锁
自旋达到阈值后无法获取到锁,则会膨胀为重量级锁,其他竞争的线程此时不会自旋而是直接阻塞等待,Mark Word中的内容会变成一个监视器对象,管理排队的线程。

monitor 对象本质上是一个同步机制,保证了同时只有一个线程能够进入临界区,在 HotSpot 的虚拟机中,是由 C++ 类 ObjectMonitor 实现的。

ObjectMonitor的属性:

ContentionQueue:是个队列,所有竞争锁的线程都会先进入这个队列中,可以理解为线程的统一入口,进入的线程会阻塞。
EntryList:ContentionQueue 中有资格的线程会被移动到这里,相当于进行一轮初筛,进入的线程会阻塞。
Owner:拥有当前 monitor 对象的线程,即 —— 持有锁的那个线程。
OnDeck:与 Owner 线程进行竞争的线程,同一时刻只会有一个 OnDeck 线程在竞争。
WaitSet:当 Owner 线程调用 wait() 方法被阻塞之后,会被放到这里。当其被唤醒之后,会重新进入 EntryList 当中,这个集合的线程都会阻塞。
Count:用于实现可重入锁,synchronized 是可重入的。

3.5锁升级过程

线程A进入synchronized开始抢锁,JVM判断当前是否是偏向锁状态,根据Mark Word中的owner 线程的Id来判断。如是是直接进入临界区内执行代码;

如果不是,则通过自旋尝试获取锁,如果获取到了则将Mark Word中的线程Id改为自己的,如果自旋失败,则膨胀为轻量级锁,自旋达到阈值还未成功则升级为重量级锁

后续的竞争线程通过自旋来尝试获取锁,自旋成功那么锁的状态仍然是轻量级锁,如果竞争失败,锁会膨胀为重量级锁,后续等待的线程都会被阻塞。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值