synchronized的实现原理与应用
synchronized实现同步的基础:Java中的每个对象都可以作为锁。具体表现为以下三种方式
1.对于普通的同步方法,锁的是当前实例对象
2.对于静态的同步方法,锁是当前类的Class对象
3.对于同步方法块,锁是synchronized括号中配置的对象
*Java对象头
- *Mark Word 存储对象的hashCode或锁的信息
- *Class Metadata Address 存储到对象类型数据的指针
- Array length 数组的长度
通过配合Mark Word 与 Class Metadata Address来实现锁的升级与绑定
为什么要引入3种锁,偏向锁,轻量级锁,重量级锁
由于线程进入到阻塞态,需要进行用户态到内核态之间的转换;其代价过高,因此引入了偏向锁与轻量级锁。
偏向锁: 当对象头被标记为偏向锁状态,并且对象头中的线程ID与当前线程ID相同,则可以优化CAS过程
轻量级锁:线程通过自旋代替阻塞;对于一些快速完成任务的线程,具有极大的性能提升
偏向锁
过程:当一个线程访问同步块时 并获取锁时,会在对象头和栈帧中的锁记录里存储锁偏向的线程ID,以后该线程在进入和退出同步块时不需要进行CAS操作来加锁和解锁,只需要简单地测试一下该线程的ID与对象头的Mark Word里是否存储着指向当前线程的偏向锁。
如果测试成功,表示线程已经获得了锁。如果测试失败,则需要再测试一下Mark Word中偏向锁的表示是否设置成1;如果没有设置,则使用CAS竞争锁;如果设置了,则尝试使用CAS将对象头的偏向锁指向当前线程