Java中的锁


HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。

实例变量:存放类的属性数据信息,包括父类的属性信息,如果是数组的实例部分还包括数组的长度,这部分内存按4字节对齐。

填充数据:数据不是必须存在的,有时候仅仅是为了字节对齐。

而Java对象头则是实现锁的基础。HotSpot虚拟机的对象头(Object Header)包括两部分信息:

  • Mark Word 用于存储对象自身的运行时数据, 如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等等,
  • Class Metadata Address 用于存放类型指针,JVM通过这个指针确定这个对象属于哪个类

下图是Mark Word的存储结构图:
Mark Word
其中轻量级锁和偏向锁是Java 6 对 synchronized 锁进行优化后新增加的。

锁的状态

锁的状态总共有四种:无锁状态、偏向锁、轻量级锁和重量级锁。随着锁的竞争,锁可以从偏向锁升级到轻量级锁,再升级的重量级锁(但是锁的升级是单向的,也就是说只能从低到高升级,不会出现锁的降级)。JDK 1.6中默认是开启偏向锁和轻量级锁的,我们也可以通过-XX:-UseBiasedLocking来禁用偏向锁。

偏向锁

当同一个线程反复去取同一个对象,我们是否每次都需要去添加锁呢?显然添加锁释放锁是会付出一些代价的,在这种情况下,java引入了偏向锁来进行优化。偏向锁的意义就在于:如果一个线程获得了锁,这个对象的锁就进入了偏向模式;那么当这个线程下次再来请求的时候,无需做任何同步的操作;

打比方就是:你认识了小红,你不断去询问小红在不在,当小红回复了你,才能开始谈话;小红发现,每次只有你去找它聊天,他觉得没必要把时间留给其他人,于是小红就给你了特权(偏向锁),下次不用询问我在不在,可以直接找我;

但是很明显如果同时有很多人都在找小红,小红是没有办法同时对多人进行回复的(不考虑群发消息,咱就是举个栗子)。这种情况下我们就会使用轻量锁;

轻量锁

轻量锁适用于以下情况:找小红聊天的人他们在交替的执行,没有重叠的时间段;
比如白天是小红的工作时间,同事来找他,晚上是小红的休息时间,家人来找他。那么白天黑夜的交替不存在重叠,同一时间下,只有一个线程会拿到小红这个对象的锁。

重量锁

But!
小红可是大忙人,于是小红在同一时间收到了"小红去打印文件"和”小红先把代码改改“的线程调用;小红说,那我不能同一时间干两件事情鸭,你们先排个队。这个时候轻量锁就需要升级为重量锁。

一个特殊的自旋锁

自旋锁(spinlock):是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值