synchronized锁的底层实现

在理解锁实现原理之前先了解一下java的对象头和Monitor,在JVM中,对象是分成三部分存在的:对象头、实例数据、对其填充
实例数据和对其填充与synchronized无关。实例数据存放类的属性数据信息,包括父类的属性信息,如果是数组的实例部分还包括数组的长度,这部分内存按4字节对齐;对其填充不是必须部分,由于虚拟机要求对象起始地址必须的8字节的整数倍,对齐填充仅仅是为了使字节对齐。
对象头是我们需要关注的重点,是synchronized 实现锁的基础,因为synchronized申请锁、上锁、释放锁都与对象头有关。对象头主要结构是由 Mark Word 和Class Metadata Address 组成,其中Mark Word 存储对象的hashCode、锁信息或分代年龄或GC标志等信息,Class Metadata Address 是类型指针指向对象的类元数据,JVM通过该指针确定该对象是哪个类的实例
锁分为四个状态:无锁状态、偏向锁、轻量级锁、重量级锁,其中无锁就是一种状态了。
锁的类型和状态都记录在Mark Word中,在申请锁、锁升级过程中JVM都需要读取对象头Mark Word的数据。
每一个锁都对应一个monitor对象,在HotSpot虚拟机中是由ObjectMonitor实现的,每个对象都存在着一个monitor与之关联,对象与其monitor之间的关系存在多种实现方式。如 monitor可以与对象一起创建销毁或当线程试图获取对象锁时自动生成,但当一个monitor被某个线程持有后,他便处于锁定状态。
ObjectMonitor 中有两个队列 WaitSet和EntryList用来保存ObjectWaiter对象列表(每个等待锁的线程会被封装成ObjectWaiter对象),owner指向持有ObjectMonitor对象的线程,当多个线程线程同时访问一段同步代码时,首先会进入 EntryList集合里,当线程获取到对象的monitor后进入Owner区域并把monitor中的owner变量设置为当前线程同时monitor中的计数器count加1,若线程调用wait()方法,将释放当前持有的monitor,owner变量恢复为null,count自减1,同时该线程进入WaitSet集合中等待被唤醒。若当前线程执行完毕也将释放monitor()并复位变量的值,以便其他线程进入获取monitor(锁)。
monitor对象存在于每个java对象的对象头中(存储的指针的指向),synchronized锁便是通过这种方式获取锁的,也是为什么java中任意对象可以作为锁的原因,同时也是notify/notiftyAll/wait等方法存在于顶级对象Object中的原因。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值