java synchronized锁的理解
mark word:存储对象的hashcode或锁记录的信息,
对象头包括:锁状态,是否是偏向锁,锁标志位
1.锁状态分类:无锁状态,偏向锁状态,轻量级锁状态,重量级锁状态。
<1>偏向锁:为了解决,在获得锁时,存在同一个对象,对锁的多次获取,释放,避免CAS操作而做的优化。
偏向锁的获得锁过程:
(1)检测mark word是否为可偏向状态,即是否为偏向锁为1,锁标志位为01.
(2)可偏向状态下,检测对象头中的线程id是否为当前线程的线程ID,是:执行(4)
(3)不是该线程id,则使用cas竞争偏向锁,若竞争成功,用当前线程的线程id替换对象头中的线程id
(4)线程获得该锁,执行同步代码
偏向锁的释放锁过程:
偏向锁的释放采用一种竞争才会释放的机制,线程不会主动释放锁,只有等到其它线程竞争锁,才会释放,
(1)等到全局安全点(没有正在执行的字节码),暂停拥有偏向锁的线程,若该线程已经不存活,将对象头设置为无锁状态,
轻量级锁的获得锁过程:
jvm在线程的栈帧中创建用于存储锁记录的空间,并将对象头中的Mark word 存储在该空间,然后线程尝试将mark word替换为指向锁记录的指针(锁标记位为00),成功:线程获取锁,失败:线程通过自旋来获取锁,
轻量级锁的释放锁过程:
线程通过cas将栈帧存储锁记录的空间Mark word替换回来,成功,锁释放,失败:存在线程线程竞争锁,锁膨胀为重量级锁。
重量级锁
重量级锁是互斥锁,线程的阻塞与唤醒需要用户态到内核态的切换。
几种锁对比:
偏向锁,适用于只有一个线程的情况,存在线程竞争时,会带来锁撤销的消耗,加锁和解锁不需要额外的消耗,只需要判断对象头中是否存在该线程ID,
轻量级锁:竞争的线程不会阻塞,通过自旋来获得锁,消耗cpu资源。
重量级锁:线程阻塞,需要用户态到系统态的切换,追求吞吐量。