偏向锁、轻量级锁、重量级锁的升级

这几个锁之间的关系和升级需要理解,重量级锁的获取和释放的开销比较大,所以不能在任何情况下都加上重量级锁;单线程的情况下锁是可以不需要的,但是需要有应对多线程的方案(锁升级);多个线程争夺锁,如果让一个线程稍微等一等能解决的问题就不要用重量级锁来完成。
jvm中的的线程的调度由用户线程是完成不了的,需要使用内核线程才能够完成。
重量级锁的开销主要是在线程从用户状态和内核状态之间的切换 ,java获取锁时,先从用户级线程切换到内核级线程去内核中获取锁,如果获取到锁就会切换回到用户级线程,如果没有获取到就阻塞在内核中等待被唤醒。当使获取到锁的线程使用完成以后释放锁就会切换回到内核级线程去唤醒阻塞在内核的线程然后切换回用户线程。所以一次获取锁的过程将会发生四次的线程状态切换,开销比较大。
为了解决这个问题所以对锁进行优化:
     偏向锁:单个线程下是不需要加锁的。它是根据的经验数据得来的依据,锁在大多数情况下是不存在竞争的并且是由同一个线程获得(也就是它是在单个线程下使用),因此引入了偏向锁,偏向第一个线程,偏向锁不会主动释放,它是在发生锁竞争的时候才会释放,如果一个锁对象前面被一个线程使用了,第二个线程来的时候会去检测是不是自己持有这把锁,如果是直接进入同步区域,如果不是则会判断持有锁的线程是否任然存活,如果是则需要发生锁升级升级成轻量级锁。
轻量级锁:能让线程稍微等一等就能解决的问题就别用锁。它是一个比偏向锁级别高的锁,可以从偏向锁升级而来,这个锁对象是由持有的线程主动释放,如果一个线程持有一把锁的时候,另外一个线程来获取同一把锁,如果失败将会自旋等待,而不是挂起线程,从而减小开销。如果线程通过自旋获取锁失败了那么锁才会升级成为重量级锁。
锁升级的过程:
1.假设刚开始A线程获取锁的时候第一次使用CAS操作来获取偏向锁;
2.第二个B线程来了检验是不是自己拥有这把偏向锁,如果是直接使用,如果不是通过CAS操作来获取锁,如果失败(因为A线程正在使用当中并且A线程任然存活,发生锁竞争)则将锁升级成为轻量级锁;
3.升级成为轻量级锁之后,线程B会使用自旋的方式来获取这个锁,如果B通过自旋的方式也一直获取不到锁,那么锁将会升级成为重量级锁,线程通过阻塞等待获取资源。

猜你喜欢

转载自blog.csdn.net/tab_yls/article/details/80935875