预见猿份
主题
首页面试题模拟面试SQL练习在线工具关于我们老苗一对一私教学员评价
实战项目
零基础学习路线项目前置基础创新WMS项目Java微服务框架与实战云岚到家项目闪聚支付项目学成在线项目青橙电商项目JVM原理与实战调优分布式事务专题Java高频面试题MySQL从入门到精通达梦数据库从入门到实战MongoDB从入门到实战PostgreSQL从入门到实战TiDB从入门到实战Java数据结构与算法Java 并发编程(JUC)实战课程老苗一对一私教学员评价
blog我的会员
  • Java 并发编程(JUC)实战课程

    • 课程介绍
    • 01 多线程入门
    • 02 线程的常用方法
    • 03 线程池
    • 04 synchronized教程
    • 05 ReentrantLock教程
    • 06 读写锁
    • 07 JMM教程
    • 08 CAS教程
    • 09 wait&notify
    • 10 常用的并发集合
    • 11 异步任务控制
    • 12 常用并发工具







----- 到底线了 -----

第7章 JMM 教程 ​

2.2 JMM ​

2.2.1 什么是JMM ​

CPU与内存交互存取数据 ​

在讲线程安全概念的时候讲到一个多个线程执行sum++导致线程不安全的例子:

ScreenShot_2026-09-20_103549_400.png

造成线程不安全的原因是多线程在交替执行sum++。

为什么sum++由多条指令组成呢?这和计算机硬件结构有关,下图是CPU与内存交互存取数据的示意图:

ScreenShot_2026-09-20_103643_016.png

CPU负责计算,内存负责存储,CPU计算速度要比CPU从内存中存取数据要快的多,所以硬件工程师在CPU中添加了高速缓存,CPU把数据从内存拿到高速缓存,CPU从高速缓存进行存取的速度要远远大于CPU从内存存取数据的速度,所以数据计算会先进入高速缓存,最后再将计算结果从高速缓存同步到内存。

JMM内存模型介绍 ​

为了适应不同的硬件,Java定义了JMM内存模型,它与计算机硬件结构相似如下:

ScreenShot_2026-09-20_103717_234.png

每个线程有自己的工作内存,工作内存相当于CPU高速缓存,共享内存相当于主内存,共享内存中存储了共享数据(对象的成员变量、类的静态变量等)。如果将JMM和JVM的内存模型对应,共享内存相当于堆内存,工作内存相当于栈内存。

JMM即Java内存模型(Java Memory Model ),它和JVM的内存模型不是一回事,JMM内存模型是描述多线程对共享数据读写的规则,旨在定义共享变量的读写规则保证线程安全。

JMM中定义线程对共享变量的操作有四个基础操作:read、write、lock、unlock。

read:将共享变量从共享内存读到工作内存。

write:将工作内存中的数据写入共享内存。

lock:锁定共享变量,此时共享变量被一个线程独占。

unlock: 释放锁,此时共享变量可被其它线程锁定。

详细的JMM请参考jsr133标准,需要获取jsr133英文版与中文版请关注预见猿份公众号,进入菜单“自学Java”-->"开发工具",查找并下载。

原子性可见性有序性 ​

JMM定义了对共享变量操作的原子性、可见性、有序性:

1、原子性

原子性是指一个操作在执行过程中不会中断不会出现多线程交替执行。

比如对一个int变量的赋值操作:

a=1;

a=2;

多线程执行这两条语句,执行结果要么a=1,要么a=2,不会出现第三个结果,这说明对int变量a的赋值操作具有原子性。

对a变量执行a++操作则不具有原子性,前边学习线程安全知道多线程执行a++存在交替执行的问题,因为a++底层由多条指令组成,不具有原子性的操作会导致线程不安全。

稍后会讲解保证原子性的解决方案。

2、可见性

可见性是指:多线程访问共享变量,一个线程修改了共享变量的值,另一个线程可以立即得到共享变量的最新值,简言之:一个线程修改共享变量对其它线程可见。

因为共享内存与工作内存之间存在数据同步,一个线程修改了共享变量还没有同步到共享内存时被其它线程读取旧值此时程序出现与预期不一致的结果,即线程不安全。

比如:线程1修改共享变量a为1,线程2要在a变为1后立即读取新值,如果a的值修改后对线程2不可见就会造成线程不安全的问题。

稍后会讲解保证可见性的解决方案。

3、有序性

有序性是指一块代码的执行顺序和代码书写顺序是一致的。

什么情况下代码的执行顺序和书写顺序不一致?当出现指令重排序时则可能违反了有序性规则。

比如下边的代码:

int a=1;

int b=2;

int c = a+b;
1
2
3
4
5
6

在执行时可以按如下顺序执行:

int b=2;

int a=1;

int c = a+b;
1
2
3
4
5
6

这时就发生了指令重排序,指令重排序在CPU和和编译器都可能存在。

多线程程序发生了指令重排序就可能导致程序执行的预期和结果不一致,导致 线程不安全。

稍后介绍保证程序有序性的解决方案。

🔒关注公众号,免费阅读全文

请免费关注 预见猿份 公众号,发送:yjoffer.com,获取解锁密码

公众号二维码微信扫码关注

关注公众号回复获取密码后,在下方输入并点击解锁,本机后续再读无需重复输入。

← 06 读写锁08 CAS教程 →








如果发现文档内容有错误或排版错乱,请及时联系站长老苗修改,不胜感激。联系我们
关于我们 | 隐私政策 | 豫ICP备2026003386号-4 | 豫公网安备41010202004008号
目录

本页无章节