Java锁升级简述

       什么是锁:在并发环境下,多线程针对同一个资源进行争抢,可能会导致数据出现异常,为了解决这个问题,就引入了锁机制。通过锁对资源进行锁定。
在这里插入图片描述
       在JVM当中,寄存器、虚拟机栈、本地方法栈是线程独享(安全)的。但是Java堆(保存所有的Java对象和数组)、方法区、运行时常量池是线程共享的,就有可能出现线程安全问题。
每个object对象都有一把锁,这个锁在对象头中,记录着这个对象在被哪个线程占用着。

对象头结构

       Java的对象分为三个部分:对象头、实例数据、对齐填充字节。
对象头存放了对象本身的运行时信息。对象头包含了两部分:Mark Word和ClassPointer。相对于实际数据,对象头属于一些额外的内存开销。因此被设计的极小以提升效率。其中,Mark Word中,就包含了锁信息。

锁状态25bit4bit1bit2bit
23bit2bit是否偏向锁锁标志位
无锁对象的hashCode分代年龄001
偏向锁线程idEpoch分代年龄101
轻量级锁指向栈中锁记录的指针00
重量级锁指向重量级锁的指针10
GC标记11
Mark Word(32位为例)

       对象内存存在一把锁,锁信息放在了对象头的Mark Word当中。在最后两位中,代表了锁标志位:无锁、偏向锁、轻量级锁、重量级锁。

synchronized关键字

       synchronized关键字可以用来同步线程,synchronized被编译后,会生成monitorenter,monitorexit两个字节码指令。JVM以此来进行线程同步。

monitor

       monitor即为同步监视器,一个线程进入了monitor,其他线程只能够等待,当且只有这个线程退出,其他线程才有机会竞争到所资源进行执行。
在这里插入图片描述

Entry Set中聚集了一些想要进入Monitor的线程,它们处于waiting状态,假设某个名为A线程成功进入了Monitor,那么它就处于active状态。假设此时A线程执行途中,遇到一个判断条件,需要它暂时让出执行权,那么它将进入wait set,状态也被标记为waiting。这时entry set中的线程就有机会进入monitor,假设一个线程B成功进入并且顺利完成,那么它可以通过notify的形式来唤醒wait set中的线程A,让线程A再次进入Monitor,执行完成后便退出。
这就是synchronized的同步机制,但是synchronized可能存在性能问题,因为monitor是依赖于操作系统的Mutex Lock来实现的,Java线程事实上是对操作系统线程的映射,所以每当挂起或唤醒一个线程都要切换到操作系统的内核态,这个操作是比较重量级的。在一些情况下,甚至切换时间本身就会超出线程执行任务的时间,这样的话,使用synchronized将会对程序的性能产生影响。
从Java6开始,synchronized关键字就进行了优化,引入了“偏向锁”,“轻量级锁”,所以锁共有四种状态,分别为:无锁、偏向锁、轻量级锁、重量级锁。

锁的四种状态
  • 无锁
    无锁顾名思义就是没有对资源进行锁定,所有线程都能够访问同一资源。在出现资源竞争的情况下,不想对资源进行锁定,但是还是想通过某种手段进行多线程的控制。假如有一个累计值,我们不想通过锁定资源的方式进行限制,但是想控制只有一个线程能修改成功的话,就可以通过CAS操作(可以看AutomaticInteger中对unsafe类的操作)。但是当出现循环的时候,某个时间的cpu占用率会变得很高,而且可能出现ABA问题(通过版本号解决)。
  • 偏向锁
    当我们开始为对象进行加锁,假如某对象被加锁了,但在实际运行的时候,只有一条线程会获取这个对锁,那么我们最理想的方式,是不要通过系统状态切换,也不通过CAS获取锁,因为那样或多或少还是消耗了一些资源。我们设想的是最好对象能够认识这个线程,只要是这个线程过来,那么对象就直接把锁交出去。我们可以认为这个对象偏爱这个线程,所以被称为“偏向锁”。
    那么偏向锁是怎么实现的呢?在Mark Word中,当锁标志为是01,那么判断倒数第三个bit是否为1,如果是1,那么代表当前对象的锁状态为偏向锁,于是再去读Mark Word的前23个bit,这23个bit就是线程ID,通过线程ID来确认想要获得对象锁的线程是不是之前所记录的线程ID。
  • 轻量级锁
    假如情况发生了变化,对象发现目前不只有一个线程,而是有多个线程正在竞争锁,那么偏向锁将会升级为轻量级锁。Mark
    Word发生变化,指向栈中Lock Record的指针。
  • 重量级锁
    倘若在轻量级锁的情况下,线程自旋次数过多,这个时候就会从轻量级锁转换成为重量级锁。Mark Word再次发生变化,指向重量级锁的指针。这个时候,其他线程试图获取锁时都会被阻塞,只有持有锁的线程释放锁之后才会唤醒这些线程。

参考: https://www.cnblogs.com/yiyepiaolingruqiu/p/11583820.html
https://www.cnblogs.com/yiyepiaolingruqiu/p/11583820.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值