synchronized原理分析


前言

synchronized原理分析。


一、synchronized是如何锁住this对象的?

堆存放的实例对象信息会有一个对象头,指向方法区中的类(类中存有类方法和类的静态变量)对象,这个对象头就是synchronized需要锁住的东西,其中对象头部包含:Mark Word(堆中的一段内存区域)、class meta address(堆指向类对象的指针或者叫地址)、array length(数组对象的长度)。最终,synchronized是根据cas修改this对象的Mark Word。

在这里插入图片描述
mark word:
在这里插入图片描述

二、synchronized中CAS修改过程

1.未锁定变成轻量级锁的原理

首先,线程会把堆中的原mark word中的状态复制到线程中,通过CAS修改mark word ,将未锁定(关闭偏向锁)修改成轻量级锁,成功则抢锁成功,失败的线程则是自旋(长时间的自旋,会占用cpu性能,然后会锁升级)

代码如下(示例):

在这里插入图片描述

2.轻量级锁升级为重量级锁的原理

代码如下(示例):
轻量级锁升级为重量级锁,对象头的状态变更了,然后对象头中的信息还需要存线程池队列(entryList)和(onwer)线程获取锁就是获取onwer,还有一个等待队列wait set。重量级抢锁跟原来写的testlock差不多。
在这里插入图片描述

三:锁升级的过程

图示:
在这里插入图片描述
未锁定,开启偏向锁的状态–>偏向锁 锁定 这个过程是属于单线程的时候才会发生,而且他加锁以后不会在解锁了。偏向锁加锁成功后,又有其他线程来访问,这时候线程会升级变成轻量级锁或者升级为未锁定,关闭偏向锁。重量级解锁会直接回到未锁定,关闭偏向锁(只是关闭了当前对象的锁)。

四:锁粗化和锁消除

锁粗化:比如一段代码有多个地方用到synchronized,然后此段代码多次执行以后,将整个代码块放到一个synchronized中,类似这样的操作就是锁粗化。不在意是否多个线程访问(也是所合并)。
示例:test()粗化成test1()

 public void test(Object arg) {

        synchronized (this){
            i++;
        }
        synchronized (this){
            i--;
        }
        //生成随机数
        synchronized (this){
            //生成随机数
        }
        synchronized (this){
            i--;
        }
    }
    public void test1(Object arg) {

        synchronized (this){
            i++;
            i--;
            //生成随机数
            //生成随机数
            i++;
        }

    }

锁消除:例如:多个StringBuffer.append(),连续执行就会导致频繁的加锁解锁,就会触发JIT编译将append()的synchronized消除掉。注意:StringBuffer是个局部变量,没有在其他线程中使用,只能有一个线程访问。

总结

synchronized底层原理就是CAS操作mark word,将修改mark word为指定的状态(锁状态:未锁定,偏向锁,轻量级锁,重量级锁)。synchronized优化方案:锁粗化,锁消除,偏向锁,轻量级锁,重量级锁;synchronized属于互斥锁。

JAVA程序运行原理分析

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值