Java synchronized偏向锁、轻量级锁、重量级锁

简介

        synchronized锁共有偏向锁、轻量级锁、重量级锁三种类型,而这三种类型的加锁方式都是相同的,写代码时不用考虑加哪种锁。使用锁时对象首先会变为偏向锁状态,当有其它线程获取锁时会升级为轻量级锁(没有竞争锁),若有线程竞争锁时,直接升级为重量级锁。

一、偏向锁

        当创建对象时该对象的对象头状态会变成偏向锁状态(即使不加synchronized也是默认偏向锁状态,即Biased状态。thread指向偏向的线程,当有线程再次获取锁时,会判断是否为偏向的线程,如果是就可以直接执行同步代码块的内容。若不是,偏向锁升级为轻量级锁。

                

       优点:加锁和释放锁的过程比较耗时,偏向锁不需要频繁的加锁和释放锁。

       注意:1、当开启偏向锁时(默认开启),创建一个对象,对象的Mark Word为偏向锁状态,偏向锁是默认延迟的,不会在程序启动时立即生效(几秒后才生效)。
        2、当禁用偏向锁时,新创建的对象为普通状态,即使该对象被synchronized修饰,也不会变为偏向锁状态。
        3、如果对象调用hashcode方法,会自动禁用偏向锁,是因为偏向锁的对象头中没办法存储hashcode,而轻量级锁和重量级锁的hashcode都存放在获得锁的线程中的栈帧中,当释放锁时会将hashcode、age等数据恢复给锁对象,对象头状态恢复为普通状态。

二、轻量级锁

        1、概念

                轻量级锁和偏向锁加锁方式一样,当偏向锁被其它线程获取时(未发生竞争),会自动升级为轻量级锁。

        2、轻量级锁的加锁和释放锁的过程:

                每个线程的栈帧都会包含一个锁记录,内部可以存储锁对象的Mark Word,如下图:

                        

                当Thread-0获取锁时,会将锁记录中的Object reference指向锁对象,并尝试用cas修改锁对象中的Mark Word,并将Mark Word的值存放在锁记录中,如果修改成功,如下:        

                    

                这样的话锁对象的最后两位就是 00 表示加了轻量级锁。上述是cas操作成功的情况,什么情况下cas操作会失败呢?

                情况一:其它线程已经持有了该对象的锁,表名此时发生了锁的竞争,轻量级锁会膨胀为重量级锁。   

                情况二:自己执行了synchronized的锁重入,那么再添加一条Lock Record作为重入的记数,如下图:

                

                当退出synchronized代码块(解锁)时,如果有取值为null的锁记录时,表示有重入,这时重置锁记录,表示重入次数减1。当锁记录不为null时,会使用cas将Mark Word值恢复给对象。

        注意:轻量级解锁过程中,cas将Mark Word的值恢复给锁对象时,如果此时锁已经膨胀为重量级锁,恢复会失败,即解锁失败,此时会走解重量级锁的流程,参照下文。

三、重量级锁

        概念:

                当线程竞争锁时会将锁膨胀为重量级锁。

        重量级锁加锁过程:

                假如线程0获得了轻量级锁,未释放锁时线程1尝试获取锁,此时轻量级锁膨胀为重量级锁,如下图:

        

                线程1加锁时发现,该对象的锁已经被别的线程持有,且锁状态为轻量级锁(后两位为00)这时线程1会为锁对象申请Monitor锁,让锁对象的Mark Word指向Monitor的地址,线程1进入Monitor的Entrylist中,进入阻塞状态,如下图:

        

        重量级锁释放锁过程:

                当线程0进入释放锁时,使用cas将Mark Worked的值恢复给锁对象时,失败,会进入重量级锁的解锁过程,即按照Monitor地址,设置Owner为null,并唤醒阻塞队列中的线程。

        注意:在重量级锁中,Object原来的Mark Word值会存放在Monitor中,当解锁时,Monitor会将Mark Word的值恢复给锁对象。

 

        

 

 

 

              

 

                  

 

                                

    

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值