从细节理解Java锁的升级

简介: 从细节理解锁的升级

线程同步

  1. 保证互斥访问,即一个对象被一个线程修改的时候,另一个线程不允许同时进行修改
  2. 保证进入同步方法或者同步代码块的每个线程,都能看到之前的修改效果

锁的升级

image-20210905095531290

以生活做类比,与锁相关的还有一些概念,比如说钥匙,柜子.钥匙用于开锁,锁用于保护柜子里的物资.只有得到了这把钥匙,我们才能去访问柜子里的资源.而锁和钥匙是一起交付的,不会出现只卖锁不卖钥匙的情形,因此正常情况下得到锁就意味着我们一定能够打开这把锁

java中的锁也是一样,只不过锁的是同步代码块,而获得锁的是线程,当一个线程获取到一个锁时也等价于获取到了该锁的钥匙.也就能访问到被锁住的代码与资源.而其他线程在此时则无法访问该块代码.

无锁

无锁就意味着,任意线程任意时刻都可以访问

偏向锁

当第一个线程第一次访问一个锁时,会通过CAS将自己的ThreadID置换到MarkWord中,并将偏向锁标志位置为1,当该线程再次访问此同步代码块时首先判断是否为偏向锁,是则继续判断ThreadId是否相同,相同就直接进入同步代码块,避免了再次用CAS的开销,如果有第二个线程来访问同一个代码块,也会先判断是否为偏向锁以及ThreadID是否相等,不相等则利用CAS去替换自己的ThreadID,如果成功,则说明第一个线程已经不在了,此时依旧为偏向锁.如果失败,说明线程一依旧占有锁,此时则将线程一暂停,设置偏向锁标识为0,并设置锁标志位为00,升级为轻量级锁,会按照轻量级锁的方式进行竞争锁。

注意

  • 当一个对象已经计算过identity hash code,它就无法进入偏向锁状态;
  • 当一个对象当前正处于偏向锁状态,并且需要计算其identity hash code的话,则它的偏向锁会被撤销,并且锁会膨胀为轻量级锁或者重量锁;

也就是说HashCode与偏向锁不能共存,jdk15以后似乎有取消偏向锁的趋势

轻量级锁

从无锁->轻量级锁

首先通过标志位判断此时同步块是否被锁定,如果没有被锁定,则在当前线程的栈帧中建立一个叫做Lock Record的空间,用于存储对象(锁)当前的Mark Word拷贝,同时还存有一个指针,然后再通过CAS尝试把对象的MarkWord更新为指向LockRecord的指针(也就是说,如果此时锁对象的MarkWordLockRecord里的相同,那么当前线程就可以获得锁)将LockRecord里的另一个指针指向当前的MarkRecord(这个用于轻量级锁的撤销),更新成功后,将锁标志位转化为00.

如果更新失败了,就说明,有另一条线程已经获取到了锁,此时失败的线程则通过自旋来不断获取锁,如果在自旋过程中成功获取了锁,就依旧保持轻量级锁的状态,否则失败线程进入阻塞状态,将锁的标志位变为10,MarkWord变成指向重量级锁的指针,成为重量级锁

//Lock Record数据结构如下
class BasicObjectLock {
  friend class VMStructs;
 private:
  BasicLock _lock; 
  oop       _obj; 
};
class BasicLock {
 private:
  volatile markOop _displaced_header;
};

注意

只有两条线程相互竞争的时候才会有轻量级锁的产生,若是两条以上的线程竞争,则直接膨胀为重量级锁

重量级锁

重量级锁就是最传统的锁,只有一个线程获得锁,其他所有线程阻塞等待唤醒

总结

一般所说的偏向锁->轻量级锁->重量级锁的流程只有在不使用HashCode且只有两个线程竞争的时候生效

如果使用hashCode则会跳过偏向锁,超过两个线程竞争,则会直接成为重量级锁.

目录
相关文章
|
3月前
|
安全 架构师 Java
Java LTS版本进化秀:从8到21的欢乐升级之旅
困惑于Java版本选择?轻松幽默地穿越Java LTS版本时光隧道,掌握从Java 8到21的关键特性。通过一家初创公司的系统升级故事,直观了解每个版本如何解决代码冗余、性能瓶颈等开发痛点,助你在技术选型中做出明智决策。
|
6月前
|
Java API 微服务
2025 年 Java 核心技术全面升级与实战应用详解
这份Java校招实操内容结合了最新技术趋势,涵盖核心技术、微服务架构、响应式编程、DevOps及前沿技术等六大模块。从函数式编程到Spring Cloud微服务,再到容器化与Kubernetes部署,帮助你掌握企业级开发技能。同时,提供AI集成、区块链实践和面试技巧,包括高频算法题与系统设计案例。通过学习这些内容,可应对90%以上的Java校招技术面试,并快速上手实际项目开发。资源链接:[点此获取](https://pan.quark.cn/s/14fcf913bae6)。
791 41
|
6月前
|
存储 Java API
MinIO Java SDK 7.1.4 升级到 8.5.17 需要注意什么
现在我需要你帮我分析对比这个两个sdk在对外的接口设计上是否有不兼容的变更
519 5
|
安全 Java 调度
Java编程时多线程操作单核服务器可以不加锁吗?
Java编程时多线程操作单核服务器可以不加锁吗?
188 2
|
9月前
|
存储 架构师 安全
深入理解Java锁升级:无锁 → 偏向锁 → 轻量级锁 → 重量级锁(图解+史上最全)
锁状态bits1bit是否是偏向锁2bit锁标志位无锁状态对象的hashCode001偏向锁线程ID101轻量级锁指向栈中锁记录的指针000重量级锁指向互斥量的指针010尼恩提示,讲完 如减少锁粒度、锁粗化、关闭偏向锁(-XX:-UseBiasedLocking)等优化手段 , 可以得到 120分了。如减少锁粒度、锁粗化、关闭偏向锁(-XX:-UseBiasedLocking)等‌。JVM锁的膨胀、锁的内存结构变化相关的面试题,是非常常见的面试题。也是核心面试题。
深入理解Java锁升级:无锁 → 偏向锁 → 轻量级锁 → 重量级锁(图解+史上最全)
Java 中锁的主要类型
【10月更文挑战第10天】
335 59
|
缓存 Java
java中的公平锁、非公平锁、可重入锁、递归锁、自旋锁、独占锁和共享锁
本文介绍了几种常见的锁机制,包括公平锁与非公平锁、可重入锁与不可重入锁、自旋锁以及读写锁和互斥锁。公平锁按申请顺序分配锁,而非公平锁允许插队。可重入锁允许线程多次获取同一锁,避免死锁。自旋锁通过循环尝试获取锁,减少上下文切换开销。读写锁区分读锁和写锁,提高并发性能。文章还提供了相关代码示例,帮助理解这些锁的实现和使用场景。
337 4
java中的公平锁、非公平锁、可重入锁、递归锁、自旋锁、独占锁和共享锁
|
Java 开发者
Java 中的锁是什么意思,有哪些分类?
在Java多线程编程中,锁用于控制多个线程对共享资源的访问,确保数据一致性和正确性。本文探讨锁的概念、作用及分类,包括乐观锁与悲观锁、自旋锁与适应性自旋锁、公平锁与非公平锁、可重入锁和读写锁,同时提供使用锁时的注意事项,帮助开发者提高程序性能和稳定性。
531 3
|
SQL Java OLAP
java实现“数据平滑升级”
java实现“数据平滑升级”
160 2