20|JMM:如何打造一个线程安全的程序?
康杨
你好,我是康杨。
在编程过程中,你有没有遇到过在运行多线程程序时想用共享变量来通讯,却发现程序结果和预期不一致的情况?这个常见的问题就是多线程编程的难点,涉及内存可见性和重排等问题。今天我们就来解决这些问题,并探讨 JVM 如何通过它的内存模型 JMM 来解决它们。
可见性问题
第一个问题出现在处理器和内存之间。现代电脑系统中,处理器速度很快,内存的读写速度却远远不能比肩。为了解决这种矛盾,引入了高速缓存,处理器将计算所需数据复制到缓存,从而加快运算速度。然而,这也引发了缓存的一致性问题,也就是说,在多处理器系统里,如果每个处理器都同时使用相同的内存,那么它们的缓存数据可能会出现差异。
处理器必须按照一些协议进行同步操作,在读写时维持缓存一致性。这里就涉及到内存可见性问题,也就是一个线程修改的状态能够即时在其他线程中可见。
重排问题
我们日常写的代码,在实际运行之前,都会经过 JVM 及底层 CPU 等各种优化,来达到最优的执行性能。但是这种优化都是基于单线程考虑的优化,如果你的程序是以多线程的方式运行,反而很容易引发各种问题。所以对于多线程的程序,知道 JVM 实际进行了哪些优化非常重要。
指令序列从源代码到实际执行的过程可能会经历以下三种重新排序。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
Java内存模型(JMM)是多线程编程中的关键概念,旨在解决内存可见性和指令重排等问题。JMM基于主内存和工作内存的交互操作,以及指令重排等优化规则,确保多线程环境下的内存可见性和操作顺序一致性。为了构建线程安全的程序,开发者可以利用JMM提供的解决方案,如Synchronized关键字、Volatile关键字、final关键字、Lock接口和原子变量等。这些解决方案能够保证共享变量的可见性、有序性和原子性,从而避免多线程并发中的问题。通过熟练掌握JMM的基本原理和内存间的交互操作,开发者能够更好地构建线程安全的Java程序。因此,JMM为多线程编程提供了重要的指导原则,帮助开发者避免内存可见性和重排问题,确保程序在多线程环境下的正确性。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《云时代的 JVM 原理与实战》,新⼈⾸单¥59
《云时代的 JVM 原理与实战》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(1)
- 最新
- 精选
- peter请教老师几个问题: Q1:编译器重排的例子,怎么禁止编译器重排列? Q2:指令并行重排的例子,指令并行,是指“a = 1”和“flag = true”这两个指令并行处理,而且并行处理的时候,“flag = true”比“a = 1”先执行吗? 另外,while (!flag),是不是多加了一个“!”?“重叠执行”就是指并行执行吗? Q3:缓存系统的重排,“处理器利用了缓存以及读写缓冲区”这句话中,“缓存”是指CPU缓存吗?“读写缓冲区”又是指什么?“负载和保存的任务”,这句话中,“负载任务”和“保存任务”分别指什么? Q4:JVM,主内存和工作内存部分。假设系统物理内存是100M,不考虑操作系统和其他应用,假设有两个进程A和B,A用10M内存,B用20M内存,那剩下的70M内存就是主内存吗? Q5:“当某个进程对某一变量进行读取或修改操作的时候,需要先把相关数据从主存搬到工作区,完成后又需要把改动后的内容重新拷贝回主存。”,对于某个进程,对于所有的变量修改都需要这样操作吗?还是只针对某些变量?2023-10-15归属地:北京
收起评论