synchronized锁详解

本文主要是对synchronized使用各个情况,加解锁底层原理的讲解

一,重量级锁

对象头

讲重量级锁之前,先了解一下一个对象的构成,一个对象是由对象头和对象体组成的,本文主要讲对象头,对象体其实就是对象的成员变量,对象头由mark word 和klass word组成,klass word就是指当前对象的类型,而mark word在正常状态下就是指对象的hashcode,所处的年代,是否是偏向锁,加锁的状态,见下图

monitor(锁)--操作系统底层实现,不由我们直接控制

接下来正式进入重量级锁的讲解,首先每一个java对象都可以关联一个monitor对象,只要我们使用synchronized,就会将该对象的markwork设置为改monitor的指针地址,并设置状态为10,见上图的第四行

 整个步骤为:

  1. 首先一开始monitor对象没有和任何对象做绑定,当第一次执行synchronized代码块时,就会将其对象与底层的monitor对象做绑定,将monitor对象的指针地址替换掉对象本身的markword
  2. 设置monitor对象的owner为当前线程的栈帧
  3. 当有第二个线程进入synchronized代码块时,首先判断当前对象的markword有没有指向monitor,没有的话,则执行前两步骤,否则去判断owner是否指向某个线程,是的话,则进入monitor的entrylist进入阻塞,等待owner执行完毕,不是的话,则执行1,2步骤
  4. 释放锁时,首先找到当前对象的引用地址,然后获取markword中的monitor对象地址,然后从monitor中清除掉owner指向的当前线程,然后从monitor中拿到对象正常状态下的markword进行重置,还原正常状态,然后唤醒entrylist中的所有线程,抢占时间按片重复上述步骤即可
  5. 当synchronized代码块出现异常也不用担心,同样会帮我们重置当前对象的状态,并唤醒entrylist中的线程,然后会抛出异常,避免死锁

二,轻量级锁

轻量级锁并不是用来替换重量级锁的,我们知道,monitor是操作系统提供给我们的对象,频繁的操作它加解锁实际上是一个很消耗性能的操作,当我们线程竞争没那么频繁的时候,比如我前一个线程执行完代码块,后一个线程才进入,那么我就没必要加锁,当竞争频繁的时候我们再升级为重量级锁

具体步骤如下:

  1. 首先当执行到 synchronized代码块时,会在当前线程栈中写入一个锁记录lock record,然后将当前对象的引用地址写入锁记录的object reference中
  2. 将当前对象的markword和锁记录的地址通过cas进行交换,状态切换为00就是轻量级锁,见图一的第三行,如果当前对象的状态为01则可以交换成功,表示当前对象由当前线程持有,如果为00则会交换失败,说明但前锁已经被别人持有了,这个时候又会分为两种情 况:
  • 第一线程重入,就是说持有锁的是当前线程,那么因为又执行了synchronized代码块,左边的栈中又写入一条栈帧锁记录   ,但是因为替换失败所以锁记录的地址为null,当前线程锁次数加一,因为本身是当前线程获取到了锁,所以仍然可以进入代码块执行,当执行完里层的synchronized代码块,就会将当前线程锁的次数减一,当执行到最外层的代码块时判断如果锁记录有值说明是最后一层,并判断当前线程锁的次数,如果为0则释放锁;
  •   第二种就是,之气获取到锁的不是当前线程,那么锁就会升级为重量锁(或者专业点说叫锁膨胀),并把对象的markword由锁记录地址替换为monitor对象的地址,并将monitor的owner指向之前线程的栈地址,将当前线程放入entrylist阻塞等待
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Java中,synchronized的升级是指在不同的场景下,的实现方式会有所不同,以提高性能和并发控制的效率。下面是synchronized的升级详解: 1. 偏向(Biased Locking):当一个线程访问同步块时,首先会尝试获取偏向。如果偏向未被其他线程占用,则当前线程会获得偏向,并标记为偏向线程ID。这样,在后续进入同步块时,无需再进行的竞争,提高了性能。只有当其他线程尝试获取偏向时,才会撤销偏向状态。 2. 轻量级(Lightweight Locking):当多个线程尝试竞争同一个时,偏向会升级为轻量级。轻量级使用CAS操作来实现加和解,避免了线程阻塞和唤醒的开销。如果CAS操作失败,表示存在竞争,会升级为重量级。 3. 重量级(Heavyweight Locking):当轻量级竞争失败时,会升级为重量级。重量级使用操作系统的互斥量(Mutex)来实现,被阻塞的线程会进入等待状态,直到被释放。重量级的竞争会导致线程的上下文切换和调度开销增加,性能较低。 synchronized的升级过程是根据实际情况和竞争情况动态进行的。在大多数情况下,的升级是逐级升级的,即从偏向到轻量级,再到重量级。这种的升级机制是为了在减少竞争时提供更好的性能,并在存在竞争时保证线程安全性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EntyIU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值