JVM整理(四)

内存模型

简单的说,JMM 定义了一套在多线程读写共享数据时(成员变量、数组)时,对数据的可见性、有序性、和原子性的规则和保障

1. java 内存模型

1.1 原子性

synchronized (同步关键字)
 

2. 可见性

2.1 退不出的循环

 

 

 分析:

2. 因为 t 线程要频繁从主内存中读取 run 的值,JIT 编译器会将 run 的值缓存至自己工作内存中的高速缓存中,减少对主存中 run 的访问,提高效率 

 

 

 

2.2 解决方法

volatile(易变关键字)
它可以用来修饰成员变量和静态成员变量,他可以避免线程从自己的工作缓存中查找变量的值,必须到主存中获取它的值,线程操作 volatile 变量都是直接操作主存

2.3 可见性

前面例子体现的实际就是可见性,它保证的是在多个线程之间,一个线程对 volatile 变量的修改对另一个线程可见, 不能保证原子性,仅用在一个写线程,多个读线程读的情况

注:

synchronized 语句块既可以保证代码块的原子性,也同时保证代码块内变量的可见性。但缺点是synchronized是属于重量级操作,性能相对更低
如果在前面示例的死循环中加入 System.out.println() 会发现即使不加 volatile 修饰符,线程 t 也能正确看到对 run 变量的修改了,想一想为什么? 
why:println方法加了synchronized关键字

3. 有序性

3.1 诡异的结果 

 

 

 

现象:指令重排,是JIT编译器在运行时的优化

3.2 解决方法 

volatile 修饰的变量,可以禁用指令重排 

3.3 有序性理解

JVM 会在不影响正确性的前提下,可以调整语句的执行顺序

 

3.4 happens-before

 

4. CAS 与 原子类

4.1 CAS(compare and swap)

 

 

 

4.2 乐观锁与悲观锁 

  • CAS 是基于乐观锁的思想:最乐观的估计,不怕别的线程来修改共享变量,就算改了也没关系,我吃亏点再重试呗。
  •  synchronized 是基于悲观锁的思想:最悲观的估计,得防着其它线程来修改共享变量,我上了锁你们都别想改,我改完了解开锁,你们才有机会。 

4.3 原子操作类 

5. synchronized 优化 

Java HotSpot 虚拟机中,每个对象都有对象头(包括 class 指针和 Mark Word)。Mark Word 平时存储这个对象的 哈希码 、 分代年龄 ,当加锁时,这些信息就根据情况被替换为 标记位 、 线程锁记录指针 、 重量级锁指针 、 线程ID 等内容

5.1 轻量级锁

 

5.2 锁膨胀 

 

5.3 重量锁

 

5.4 偏向锁

 

5.5 其它优化

 

posted @   梦醒如赦  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
历史上的今天:
2021-05-03 装载问题(回溯法)
2021-05-03 凸多边形最优三角剖分(动态规划)
点击右上角即可分享
微信分享提示