java synchronised 机制
作用范围:静态代码块、方法
写法如下:
Object lock = new Object();
synchronised(lock){
// 业务代码
}
多线程对锁的竞争,就是对共享资源lock 的竞争;
抢夺lock 对象monintor
,修改锁标识
;
对象的内存布局
偏向锁
锁竞争中,同一个线程获得锁的概率大,为了让获取锁的代价更低
,引入了偏向锁;
当一个线程获取到锁,会在对象头中存储线程id
;后续这个线程进入和退出代码块时,不需要再次加锁和释放锁;
偏向锁的获取和撤销
1)获取锁的对象,判断是否处于可偏向的状态 ( lock_1, 且 threadId 为 null )
2)可以偏向,通过cas ,把当前线程id 写入 Markword;
- 写入成功,锁对象升级为偏向锁
- 写失败,说明其他线程已经获取到锁,锁升级为轻量级锁(这个操作需要等到全局安全点,也就是没有线程在执行字节码)
3)如果是已偏向状态,需要检查 markword 中存储的ThreadID 是否等于当前线程的 ThreadID
- 如果相等,不需要再次获得锁,可直接执行同步代码块
- 如果不相等,说明当前锁偏向于其他线程,需要撤销偏向锁并升级到轻量级锁
轻量级锁
轻量级锁设置失败,会升级为轻量级锁;
相比于偏向锁,轻量级锁会再当线程 创建 锁记录, 将对象头中的锁记录指向当前线程;
也就是说偏向锁比较的是 线程id是否与当前线程一致; 轻量级锁比较的是,锁对象的指针是否指向自己;
重量级锁
轻量级锁升级为重量级锁后,就只能被挂起阻塞来等待唤醒了;
锁的转化
注意点:
- 1)锁的升级是不可逆向的
- 2)偏向锁cas替换threadId 失败后情况?
- 3)轻量级锁到重量级锁的转化?
- 轻量级锁和偏向锁都有CAS操作,两者区别?