1.底层原理
synchronized 的底层原理是monitor, Monitor 被翻译为监视器,是由JVM 提供,c++实现的
2.Monitor 结构
Monitor 有三个属性: WaitSet 、EntryList、Owner ,再执行代码的时候,会将锁与monitor 关联,判断 Owner 是否为空,如果为空,当前线程就可直接获取Owner,;如果Owner 不为空,那么就会将线程放入EntryList 中,当一个线程调用了wait方法后,就会进入WaitSet;
3.锁升级
monitor实现的锁属重量级锁,里面涉及了用户态和内核态的切换、进程上下文的切换,成本较高、性能比较低
在jdk1.6 引入了两种新型锁机制:偏向锁和轻量级锁,它们的引入是为了解决在没有多线程竞争或者基本没有竞争的场景下因使用传统锁机制带来的性能开销问题
4.对象锁如何关联monitor
在HotSpot虚拟机中,对象在内存中存储的布局可分为3块区域:对象头、实例数据和对齐填充
MarkWord组成如下:
hashcode:25位的对象标识Hash码
age: 对象分代年龄(即分代回收的次数)占四位
biased_lock:偏向锁标识,占1位,0表示没有开始偏向锁,1表示开启了偏向锁
thread:持有偏向锁的线程ID,占3位
epoch:偏向时间戳,占2位
ptr_to_lock_record:轻量级锁状态下,指向栈中锁记录的指针,占30位
ptr_to_heavyweight_nonitor:重量级锁状态下,指向对象监视器Monitor的指针,占30位
在MarkWord 存放了Monitor对象的指针,由此实现锁关联
5.轻量级锁
在很多情况下,在JAVA程序运行时,同步代码块中的代码都是不存在竞争的,不同的线程交替执行同步代码块中的的代码
这种情况下,用重量级锁是没必要的,因此JVM引入了轻量级锁的概念
轻量级锁修改了对象头的锁标志,相对重量级锁性能
6.偏向锁
轻量级锁在没有竞争时(就自己这个线程),每次重入仍需要进行CAS操作,JAVA6 中引入了偏向锁来做进一步优化:只有第一次使用CAS将线程ID设置到对象的MarkWord头,之后发现这个线程ID就是自己的就表示没有竞争,不用重新CAS,以后只要不发生竞争,这个对象就归该线程所有
7.总结
JAVA中的synchronize有偏向锁、轻量级锁、重量级锁三种形式,分别对应了锁只被一个线程持有、不同线程交替持有锁、多线程竞争锁三种情况