synchronized介绍

synchronized

原理:

从JVM规范中可以看到Synchonized在JVM里的实现原理,JVM基于进入和退出Monitor对象来实现方法同步和代码块同步,但两者的实现细节不一样。代码块同步是使用monitorenter 和monitorexit指令实现的,而方法同步是使用另外一种方式实现的,通过编译之后,同步方法与普通方法不同是被加入了一个acc_synchronized标识,然后jvm通过识别这个标识来确定这是一个同步方法。但是,方法的同步同样可以使用这两个指令来实现。 monitorenter指令是在编译后插入到同步代码块的开始位置,而monitorexit是插入到结束位置和异常处,JVM要保证每个monitorenter必须有对应的monitorexit与之配对。任何对象都有一个monitor与之关联,线程执行到monitorenter 指令时,将会尝试获取对象所对应的monitor的所有权,即尝试获得对象的锁。

优化

在早期的时候,sync他是重量级的锁,就是操作系统层面的锁,需要从用户态切换到内核态。这是非常耗时的操作,性能低。

在java6之后,引入了一系列的优化,锁升级。随着的竞争加剧,锁会一步步升级。从低到高是:无锁,偏向锁,轻量级锁,重量级锁,并且是不可降级的。

对象的内存分布:

0 - 4 markword

4 - 8 markword

markword存储锁信息,gc信息

8 - 12 指向.class

以上统称为对象头。

后面是成员变量占的位置,不足8的整数倍,需要补字节到8的整数倍

在这里插入图片描述

重量级锁中指向互斥量的指针实际是指向monitor对象。

锁升级:

由低到高:无锁状态、偏向锁状态、轻量级锁状态(自旋锁)和重量级锁状态
在这里插入图片描述

偏向锁,轻量级锁,都是在用户态的。

用户态–》内核态 : 操作系统执行终端0x80

轻量级锁-------重量级锁:

jdk1.6之前:可以设置升级的线程自旋的次数阈值或者自旋的线程数阈值

jdk1.6之后:自适应,别设置了。

jvm启动时候的,有一段时间是不会启动偏向锁的,因为偏向锁适合的无线程竞争的情况,在明确知道会有多线程竞争的情况的时候,请直接使用轻量级锁,此时轻量级锁的效率可能更高,因为开始就启动偏向锁,还是会升级为轻量级锁,但是中间有一个偏向锁撤销的过程,浪费cpu资源。jvm启动必定是存在多线程竞争,所以jvm会延迟开启偏向锁。默认4s,也可以通过参数设置(-xx: BiasedLockingStartDelay== yourValue (unit:ms)

禁用偏向锁:xx - UseBiasedLocking

匿名偏向:

markword中的线程指针没有指向任何线程:匿名偏向。

如果synchronized(对象),对象中的markword中的偏向锁指针指向当前线程数,这个时候就不是匿名偏向锁了。

自旋锁

​ 共享变量。

自旋锁缺点:

在这里插入图片描述

锁重入

一个方法可能被多个方法调用,而这个多个方法的同步逻辑不一样。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

zhou吗

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

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

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

打赏作者

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

抵扣说明:

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

余额充值