千家信息网

Java并发编程之volatile与JMM多线程内存模型实例分析

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,本篇内容主要讲解"Java并发编程之volatile与JMM多线程内存模型实例分析",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Java并发编程之vola
千家信息网最后更新 2026年10月31日Java并发编程之volatile与JMM多线程内存模型实例分析

本篇内容主要讲解"Java并发编程之volatile与JMM多线程内存模型实例分析",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Java并发编程之volatile与JMM多线程内存模型实例分析"吧!

一、通过程序看现象

在开始为大家讲解Java 多线程缓存模型之前,我们先看下面的这一段代码。这段代码的逻辑很简单:主线程启动了两个子线程,一个线程1、一个线程2。线程1先执行,sleep睡眠2秒钟之后线程2执行。两个线程使用到了一个共享变量shareFlag,初始值为false。如果shareFlag一直等于false,线程1将一直处于死循环状态,所以我们在线程2中将shareFlag设置为true。

public class VolatileTest {  public static boolean shareFlag = false;  public static void main(String[] args) throws InterruptedException {    new Thread(() -> {      System.out.print("开始执行线程1 =>");      while (!shareFlag){  //shareFlag = false则一直死循环        //System.out.println("shareFlag=" + shareFlag);      }      System.out.print("线程1执行完成 =>");    }).start();    Thread.sleep(2000);    new Thread(() -> {      System.out.print("开始执行线程2 =>");      shareFlag = true;      System.out.print("线程2执行完成 =>");    }).start();  }}

如果你没有学过JMM线程模型,可能你看完上面的代码,希望得到的输出结果是下面这样的:

开始执行线程1 =>开始执行线程2 =>线程2执行完成 =>线程1执行完成=>

如下图所示,正常人理解这段代码,首先执行线程1进入循环,线程2修改shareFlag=true,线程1跳出循环。所以跳出循环的线程1会打印"线程1执行完成=>",但是经过笔者实验,**"线程1执行完成=>"不会被打印,线程1也没有跳出死循环**,这是为什么呢?

二、为什么会产生这种现象(JMM模型)?

要解释上面提到的问题,我们就需要学习JMM(Java Memory Model)Java 内存模型,笔者觉得叫做Java多线程内存模型更准确一些。

  • 首先,在JMM中每个线程有自己的工作内存,在程序启动的时候,线程将共享变量加载(read&load)到自己的工作内存中,加载到线程工作内存中的内存变量是主内存中共享变量的副本。也就是说此时shareFlag在内存中有三个副本,值都等于false。

  • 当线程2执行shareFlag=true的时候将其工作内存副本修改为shareFlag=true,同时将副本的值同步写回(store&write)到主内存中。

  • 但是线程1的工作内存中的shareFlag=false没有发生变化,所以线程1一直处于死循环之中。

三、MESI 缓存一致性协议

按照上文的实验以及JMM模型,线程2修改的共享变量的值,线程1感知不到。那怎么样才能让线程1感知到共享变量的值发生了变化呢?其实也很简单,给shareFlag共享变量加上volatile关键字就可以了。

public volatile static boolean shareFlag = false;

其底层原理是这样的,加上volatile关键字提示JMM遵循MESI 缓存一致性协议,该协议包含如下的缓存使用规范(看不懂可以不看,下文会用简单的语言及例子描述一下)。

  1. Modified:代表当前Cache行的数据是修改过的(Dirty),并且只在当前CPU的Cache中是修改过的;此时该Cache行的数据与其他Cache中的数据不同,与内存中该行的数据也不同。

  2. Exclusive:代表当前Cache行的数据是有效数据,其他CPU的Cache中没有这行数据;并且当前Cache行数据与内存中的数据相同。

  3. Shared:代表多个CPU的Cache中都会缓存有这行数据,并且Cache中的数据与内存中的数据一致;

  4. Invalid:表示当前Cache行中的数据无效;

上文中的缓存使用规范可能过于复杂,简单的说就是

  • 当线程2修改shareFlag的时候(参考Modify),告知bus总线我修改了共享变量shareFlag,

  • 线程1对Bus总线进行监听,当它获知共享变量shareFlag发生了修改就会将自己工作内存中的shareFlag副本删除使其失效。

  • 当线程1再次需要使用到shareFlag的时候,发现工作内存中没有shareFlag变量副本,就会重新从主内存中加载(read&load)

到此,相信大家对"Java并发编程之volatile与JMM多线程内存模型实例分析"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

线程 内存 数据 变量 模型 工作 循环 副本 缓存 代码 时候 实例 实例分析 分析 编程 一致 代表 学习 不同 一致性 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 哈尔滨大商圈互联网科技有限公司 互联网科技作文 互联网与新科技 互联网科技公司官网 云电互联网科技 互联网科技美容 互联网养老 桔豆科技 广州优美互联网科技 互联网企业和科技型企业 宁夏科技产业互联网案例 深圳育鹏互联网科技有限公司招聘 互联网新科技动漫ppt素材 朱啸虎曾投资哪些互联网科技企业 城市宝互联网科技有限公司 互联网时代科技型公司的机会 艺电能源互联网科技有限公司招聘 广西泛欧互联网科技有限公司 互联网金融金融科技 北京瑞云互联网科技有限公司 利用互联网等科技手段 亿人帮互联网科技有限公司 易互联网科技有限公司 金融科技和互联网金融 互联网科技素材视频竖屏 互联网公司会议桌创意科技软装饰 辽宁互联网新科技 民营互联网公司国防科技 互联网金融科技名词解释 广西泛欧互联网科技有限公司 小牛互联网科技有限公司地址
0