多线程(锁升级, 锁消除, 锁粗化)

简介: 多线程(锁升级, 锁消除, 锁粗化)

锁升级

JVM 将 synchronized 锁分为四个状态: 无锁, 偏向锁, 轻量级锁, 重量级锁.

JVM 会根据清空, 自动进行锁升级.


偏向锁

偏向锁不是真的 “加锁”, 只是给锁住的资源做了一个标记, 记录这个锁属于哪个线程.

如果后续没有其他线程来竞争锁, 那么就不用进行其他操作 (减少了加锁解锁的开销)

如果后续有其他线程来竞争锁, 就会根据标记, 取消 偏向锁状态, 进入轻量级锁状态

轻量级锁

轻量级锁即自适应的自旋锁

synchronized 的轻量级锁是通过 CAS 来实现

  • 通过 CAS 检查并更新一块内存
  • 如果更新成功, 则认为加锁成功
  • 如果更新失败, 则认为锁被占用, 继续自旋式等待(并不放弃 CPU, 以便解锁后能更快获得锁)

自适应的含义

自旋锁是一直让 CPU 空转, 比较浪费 CPU 资源

自适应的意思是 : 自旋不会一直持续进行, 到达一定的时间/重试次数, 就停止自旋(放弃 CPU 等待)


重量级锁

自旋锁经过一定时间/重试次数, 依旧不能获取锁, 就会锁升级为重量级锁

此处的重量级锁就是指用到内核提供的 mutex.

  • 执行加锁操作, 先进入内核态
  • 在内核态判定当前锁是否已被占用
  • 如果锁未被占用, 则加锁成功, 并切换回用户态
  • 如果该锁被占用, 则加锁失败. 此时线程进入锁的等待队列, 挂起. 等待 操作系统 唤醒
  • 当这个锁被其他线程释放, 操作系统唤醒等待队列中挂起的线程, 该线程尝试获取锁

锁消除

编译器 和 JVM 对于代码的优化操作

如果编译器 + JVM 判定你的代码中加的锁没有用到 (比如单线程环境下的加锁操作), 就会自动消除锁

eg :

StringBuffer sb = new StringBuffer();
sb.append("a");
sb.append("b");
sb.append("c");
sb.append("d");

StringBuffer.append() 涉及加锁解锁操作, 但是如果在单线程环境下运行此代码, 那么这些加锁解锁操作就会浪费不必要的资源, 就会被自动消除掉(编译阶段)


锁粗化

锁的粒度 : 单个锁所保护资源的数据量, 我们以 来表示

锁粗化就是: 一段逻辑中多次出现加锁解锁操作, 编译器 + JVM 就会自动将这些操作合并为一个加锁解锁操作 (加锁和解锁操作涉及资源的消耗)

下面代码就是把50000次加锁解锁操作合并为一个加锁解锁操作, 节省了很多资源消耗


目录
相关文章
|
2月前
|
安全 Java 编译器
线程安全问题和锁
本文详细介绍了线程的状态及其转换,包括新建、就绪、等待、超时等待、阻塞和终止状态,并通过示例说明了各状态的特点。接着,文章深入探讨了线程安全问题,分析了多线程环境下变量修改引发的数据异常,并通过使用 `synchronized` 关键字和 `volatile` 解决内存可见性问题。最后,文章讲解了锁的概念,包括同步代码块、同步方法以及 `Lock` 接口,并讨论了死锁现象及其产生的原因与解决方案。
81 10
线程安全问题和锁
|
2月前
|
安全 Java 调度
Java编程时多线程操作单核服务器可以不加锁吗?
Java编程时多线程操作单核服务器可以不加锁吗?
44 2
|
2月前
|
存储 缓存 安全
【Java面试题汇总】多线程、JUC、锁篇(2023版)
线程和进程的区别、CAS的ABA问题、AQS、哪些地方使用了CAS、怎么保证线程安全、线程同步方式、synchronized的用法及原理、Lock、volatile、线程的六个状态、ThreadLocal、线程通信方式、创建方式、两种创建线程池的方法、线程池设置合适的线程数、线程安全的集合?ConcurrentHashMap、JUC
【Java面试题汇总】多线程、JUC、锁篇(2023版)
|
1月前
|
运维 API 计算机视觉
深度解密协程锁、信号量以及线程锁的实现原理
深度解密协程锁、信号量以及线程锁的实现原理
33 1
|
1月前
|
Java 应用服务中间件 测试技术
Java21虚拟线程:我的锁去哪儿了?
【10月更文挑战第8天】
32 0
|
1月前
|
安全 调度 数据安全/隐私保护
iOS线程锁
iOS线程锁
26 0
|
1月前
|
Java API
【多线程】乐观/悲观锁、重量级/轻量级锁、挂起等待/自旋锁、公平/非公锁、可重入/不可重入锁、读写锁
【多线程】乐观/悲观锁、重量级/轻量级锁、挂起等待/自旋锁、公平/非公锁、可重入/不可重入锁、读写锁
31 0
|
1月前
|
安全 Java 程序员
【多线程-从零开始-肆】线程安全、加锁和死锁
【多线程-从零开始-肆】线程安全、加锁和死锁
43 0
|
1月前
|
安全 Linux
Linux线程(十一)线程互斥锁-条件变量详解
Linux线程(十一)线程互斥锁-条件变量详解
|
2月前
|
存储 算法 Java
关于python3的一些理解(装饰器、垃圾回收、进程线程协程、全局解释器锁等)
该文章深入探讨了Python3中的多个重要概念,包括装饰器的工作原理、垃圾回收机制、进程与线程的区别及全局解释器锁(GIL)的影响等,并提供了详细的解释与示例代码。
28 0

相关实验场景

更多