Java锁优化

1、总述

我们知道Java的锁有两种形式:

  • 一是synchronized,它是由JVM底层实现的,是java语言的关键字,底层是依赖对象内部的monitor锁来实现的,而monitor又依赖操作系统的MutexLock(互斥锁)来实现的,所以在JDK6.0之后,java对synchronized进行了优化,即引出了 偏向锁、轻量级所、自旋锁等概念。
  • 二是重入锁lock,它是jdk实现的一个接口,是在java的基础上通过一系列方式(比如说AQS)实现的锁,其底层用到了CAS等原理。

两者比较:

  • Synchronized,java关键字,底层由jvm调用os的MutexLock实现,不可响应中断,锁粒度不好控制,不够灵活
  • ReentrantLock,jdk实现,底层由CAS实现,并没有涉及到os的调用,可响应中断,灵活度更高,粒度更细

2、Java对象头中的Mark Word

HotSpot中,Java的对象内存模型分为三部分,分别为对象头、实例数据和对齐填充。而对象头中分为两部分,一部分是“Mark Word”(存储对象自身的运行时数据,32bit或64bit,可复用);另一部分是指向它的类的元数据指针。

因为synchronized是Java对象的内置锁,所以其优化策略(即偏向锁等)的信息都包含在Mark Word中,让我们先看一下Mark Word的结构。
在这里插入图片描述

其中最重要的是“锁标志位”和“是否偏向锁”,锁标志位代表了当前对象内置锁的状态,不同的锁状态下Mark Word存储的信息是不同的,因此称为可复用。

3、synchronized锁优化

为了解决synchronized这种重量级锁的性能问题,于是引出了如下几种形式的锁:

  • 偏向锁:主要是用于多线程竞争情况极少的情况,基本上都是同一个线程请求该锁的时候。其基本原理就是当某个线程第一次获取该锁的时候,该锁变量就在其对象头的MarkWord中将偏向锁标志位置为1,并在偏向锁的线程ID标志位中记录此次请求的线程ID。当其他线程请求该锁时,该锁变量就判断其线程ID是否一致,不一致,则当前线程通过CAS操作竞争锁,若竞争成功,则将Mark Word中线程ID设置为当前线程ID,然后执行同步代码,若竞争失败,就升级为轻量级锁。
  • 轻量级锁:当多线程并发请求时,偏向锁就失效,这时就在该锁变量中将锁标志位置为00,并指向持有该锁的线程对应的堆栈。当其他线程再次请求该锁时,该锁就通过比较其指向的线程堆栈是否一致来判断,若不一致,则进入自旋状态。
  • 自旋锁:自旋锁实际就是在轻量级锁上加的一个小优化,即当锁被占用时,该线程不会立即进入阻塞态,而是会继续几个空循环,来不断尝试获取锁,因为对于线程而言挂起操作会引发内核级别的操作,从用户态到内核态再到用户态,这是极度浪费时间的,所以采取自旋操作,可以提高锁的性能。
  • 重量级锁:即当有其他线程占用锁时,当前线程会进入阻塞状态,这是最浪费时间的锁,只会在线程占用锁的时间十分长的情况下才使用。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值