有兴趣并发编程的小伙伴可以看看这个视频,个人感觉还不错
以下代码也是看下面的视频总结来的
全面深入学习java并发编程,java基础进阶中级必会教程
这里写目录标题
- 简介
- 对象头
- Mark word的结构
- Monitor工作原理
简介
在java虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头、实例数据和对齐填充。
这篇文章主要讲解对象头
对象头
这里以32位虚拟机举例
数组对象比普通对象多了一个数组长度
普通对象
数组对象
对象头(Object Header)分为Mark word和Klass Word和array length(数组长度,只有数组对象才有)
- Mark word:用于存储对象自身的运行时数据,比如加的哪种锁,没有锁的时候hashcode,age等信息
- Klass Word:Klass Word相等于指针,存的相当于是类对象
- array length:存的数组长度(只有数组对象才有)
Mark word的结构
State:
Normal表示无锁:
- hashcode:对象的hashcode值,占25位
- age:分代年龄,当到达15之后就被分配到老年代,占4位
- biased_lock:是否是偏向锁:占1位
- 标志为01:表示没有与任何锁关联,也就是无锁:占2位
Biased表示偏向锁:
- thread:线程id
- epoch:
- age:分代年龄
- biased_lock:是否是偏向锁
- 标志为01:表示没有与任何锁关联,也就是无锁
Lightweight Locked表示轻量级锁:
- ptr_to_lock_record:30:表示指向轻量级锁
- 标志位00:表示代表是轻量级锁
Heavyweight Locked表示重量级锁:
- ptr_to_heavyweight_monitor:30:表示指向重量级锁
- 标志位10:表示代表的是重量级锁
Marked for GC表示被垃圾回收了
- 标志位11:代表被垃圾回收了
Monitor工作原理
什么叫Monitor?
Monitor被翻译为监视器或管程(由操作系统提供)
每个java对象都可以关联一个Monitor对象,如果使用synchronized给对象加锁(重量级)之后,该对象的Mark Word就被设置指向了Monitor对象的指针
流程:
1.首先如果一个线程要执行synchronized代码块,首先会尝试与Monitor对象进行关联(一个对象对应一个Monitor)
怎么进行关联呢?
原先对象头的状态是无锁,里面存储了hashcode等内容,现在需要将obj对象和Monitor对象关联,就要将Mark word里面的最开始无锁状态的hashcode,age都不要了,变成重量级锁,ptr_to_heavyweight_monitor指向Monitor地址,标志位由01变成10.
变成:
2.然后obj的Mark Word指向Monitor,线程指向Owner代表当前Monitor的主人是Thread-2
3.如果此时又有线程Thread1准备执行synchronized,发现MarkWord以及关联了一个Monitor,然后检查Owner有主人吗,发现Owner有主人,而且Owner只能有一个主人,然后这个线程Thread1只能进入EntryList(等待队列),进行等待!
在这里插入图片描述 4.如果线程2执行结束,释放掉锁,这时候Monitor中的Owner就没主人了,就看jdk底层实现调用EntryList中的其中一个线程去执行synchronized,去成为Monitor的主人
这就是对于一个Monitor锁实现的原理解释
注意:
进入synchronized的必须是同一个对象
不加synchronized的对象不会关联Monitor