1.什么是Synchronized?
Synchronized是一种互斥锁,一次只能允许一个线程进入被锁住的代码块
Synchronized是Java的一个关键字,能够将代码块,方法锁起来
情况有三种:
如果Synchronized修饰的是实例方法,锁的是对象实例
如果Synchronized修饰的是静态方法,锁的是class实例
如果Synchronized修饰的是代码块,锁的是传入Synchronized的对象实例
2.Synchronized的原理
当修饰方法时依靠ACC-Synchronized来标识
修饰代码块时,依靠的是monitorenter和monitorexit指令
在 内存中一个对象由三部分组成
对象头,实际数据,填充等
对象头主要是Mark Word
Mark Word会记录关于锁的信息
且每个对象都会有一个与之对应的monitor对象,moniror对象存储着当前持有锁的线程和等待锁的队列
3.jdk1.6的优化
1.6之前是重量级锁,每次线程进入同步代码块/方法时monitor对象把线程的id存储,设置Mark Word的monitor对象地址
并把阻塞的线程也存储到monitor中
其加锁依赖的是操作系统的mutex(互斥锁)指令,有用户态和内核态的切换。性能损耗明显
1.6之后
出现了无锁,偏向锁,轻量级锁和重量级锁
偏向锁就是JVM认为只有某个线程才会执行这个同步代码
所以会在MarkWord中记录线程ID,只要线程来执行代码,就会对比线程id是否相等,相等就可以获取到锁执行同步代码
若不相等就CAS修改线程ID,若CAS修改成功,获取到锁,执行代码
若失败
那么说明有竞争环境,锁会升级,偏向锁撤销变为轻量级锁
在轻量级锁情况下,线程会在栈帧中创建Lock Record.会把Mark Word的信息拷贝进去。
线程执行到同步代码时,CAS成功则获得轻量级锁,失败后变为重量级锁
总结:
重量级锁用到monitor对象,而偏向锁则在MarkWord中记录ID进行比较
轻量级锁则是拷贝MarkWord到Lock Record中用CAS+自旋的方式获取
只有一个锁在临界区,偏向锁
在MarkWord中记录线程ID,只要线程来执行代码,会对比线程ID是否相等,相等则直接获取到锁
不相等则用CAS来尝试修改若成功就能获取到锁执行代码
如果失败那么就偏向锁撤销,升级为轻量级锁
多个锁交替进入临界区,轻量级锁
在轻量级锁下,会把MarkWord拷贝到Lock Record(在栈帧中创建)中.
线程执行到同步代码时,CAS尝试获取修改LockRecord,若修改成功则获取到轻量级锁
用CAS加自旋的方式来获取锁.
若修改失败自旋次数达到一定次数后自动升级为重量级锁
多个锁同时进入临界区,重量级锁
Synchronized原理
于 2022-03-03 21:06:28 首次发布