synchronized称为重量级锁,在JDK1.6后对它进行了多种优化,引入了偏向锁和轻量级锁。
原理:在JVM中基于进入和退出Monitor(监视器)对象来实现的,编译后monitorenter指令插入到同步代码块的开始位置,而monitorexit是插入到结束和异常处。
在内存里的存储结构和升级过程:
HotSpot对象头分为两部分:第一部分存储类如哈希码、GC分代年龄、锁标志,第二部分存储指向方法区的对象类型数据指针。
1)、偏向锁:检查对象头偏向锁标志是否设置为1,如果没有为1进行CAS操作把对象头指向当前线程ID,如果当前线程再次进入只要检查对象头的Mark Word里是否存储指向当前线程的偏向锁,如果有直接进入同步代码块。当线程竞争偏向锁时,偏向锁撤销,锁升级为轻量级锁。
2)、轻量锁:在代码块进入同步块时,如果同步对象没有被锁定,虚拟机在当前线程的栈帧中建立一个锁记录空间,用于存储存储锁对象的Mark word拷贝,虚拟机用CAS操作将对象Mark word更像为LockRecord的指针,如果成功了就拥有了锁。如果CAS失败,检查对象的Mark Word是否指向当前线程的栈帧,如果有说明了当前线程已经拥有锁,可以进入同步块执行;否则锁对象已经被其他线程抢占将会进行一段时间自旋,如果自旋还是失败获得锁 将膨胀为重量级锁。
锁应用的三种表现:
对于普通同步方法,锁是当前实例对象。
对于静态同步方法,锁是当前类的Class对象。
对于同步代码块,锁是Synchronized括号里的对象。