目录
线程的状态转换中锁的升级过程
三种锁的优缺点
无锁--》偏向锁--》轻量级锁--》重量级锁 这三个说的是Synchonized重量级转换
没有竞争偏向锁,轻微竞争轻量级锁,重度竞争重量级锁
线程的状态转换中锁的升级过程
就绪队列随时可能被cpu调用,阻塞队列中的线程得在加锁资源被线程释放之后通知阻塞队列,然后该线程进入就绪队列参与竞争
一个线程进入运行状态先判断所需资源有没有加锁,如果加锁进入堵塞队列,如果没有的话给他加上锁。
虽然是多线程访问一定的资源,但是不是在相同的时间段内,就不是真正的并发了。而加锁的过程很麻烦。
在没什么并发的情况下,我们就没必要加锁释放锁,这个时候用偏向锁
偏向锁:是一种简化的加锁和释放锁的过程。加偏向锁之后,当一个线程访问同步块并获取锁时,会在对象头和栈帧中的锁记录里存储锁偏向的线程ID,以后该线程在进入和退出同步块时不需要进行CAS操作来加锁和解锁,只需简单地测试一下对象头的Mark Word里是否存储着指向当前线程的偏向锁。
偏向锁适用于几乎没有并发的时候,虽然访问一个线程,但是不是同一时间
轻量级锁:没有进入阻塞队列,仍在就绪队列而是有个死循环(CAS实现自旋锁),以非常高的频率过来查看,一看锁释放后立刻加锁。加锁的速度非常快但是会造成cpu的消耗
线程逐步增多,一个持有锁,其他全部自旋,对CPU的消耗很大。轻量级锁的缺点就是在并发高时,对cpu的损耗极大
总线的宽度为36~41位,64字节的数据往回更新需要两个批次,这两个批次的传输之间可能产生问题。
轻量级锁加锁:线程在执行同步块之前,JVM会先在当前线程的栈桢中创建用于存储锁记录的空间,并将对象头中的Mark Word复制到锁记录中,官方称为Displaced Mark Word。然后线程尝试使用CAS将对象头中的Mark Word替换为指向锁记录的指针。如果成功,当前线程获得锁,如果失败,表示其他线程竞争锁,当前线程便尝试使用自旋来获取锁。
轻量级锁解锁时,会使用原子的CAS操作将Displaced Mark Word替换回到对象头,如果成功,则表示没有竞争发生。如果失败,表示当前锁存在竞争,锁就会膨胀成重量级锁。
所以当高并发时,竞争锁失败时进入阻塞队列,在就绪队列全部释放锁后,从阻塞队列挑一个执行,虽然加锁释放锁的过程麻烦,但是对cpu的损耗少,总体时间少
没有竞争偏向锁,轻微竞争轻量级锁,重度竞争重量级锁。轻微竞争的时候cpu经得起消耗,高并发时cpu经不起消耗了,就会转重量级锁(高并发时,虽然重量级锁性能不好,但是对cpu的损耗小,相比另外两个反而总体性能会变好)