当前位置: 首页 > news >正文

并发编程可见性

一句话定义

可见性就是当一个线程修改了某个共享变量,其他线程能够立马看到这个最新变化的结果。

理解过程 #内存模型

核心点:CPU的内存模型、硬件的MESI、JIT指令冲排序
存数据:多核CPU的架构下,计算机要某个变量会先发起一个为写入准备的读请求(RFO),分别从L1->L2->L3查找。如果都不存在(缓存未命中),则去内存中查找(必然命中)。在将内存中的值加载到L1缓存之前由L3协调,使其他核心中包含该变量的整个缓存行副本失效。随后数据被加载到L1缓存,核心立即获得独占权。L1对该变量赋值并将状态改成已修改L3会记录此独占状态。此刻主内存中的值还是旧值。
读数据: 当核心2想要读取存在于核心1(状态为M)的数据时,核心2会先查看自身缓存。未命中后,请求最终到达L3。L3发现数据由核心1独占且已修改,会触发缓存一致性协议。此时,通常有两种结果

  1. 高效干预:核心1嗅探到请求,直接将自己L1/L2中的最新数据返回给核心2(可能同时写回L3),核心2将数据载入自己的L1。

  2. 标准写回:核心1先将数据写回L3,随后L3再将数据提供给核心2,数据会填充核心2的L2和L1缓存
    无论哪种方式,最终核心1和核心2的该缓存行状态都变为共享

内存模型
image

问题:MESI保证了硬件层面的缓存内存一致性,就算Java编译器导致指令重排序也不应该出现下面这个程序的问题,主线程修改了flag的值,但是线程t1仍旧不会停止,怎么解释

public class Visible {  public static boolean flag = true;  public static void main(String[] args) throws InterruptedException {  Thread t1 = new Thread(() -> {  while (flag) {  // do something  }  System.out.println("t1 结束");  });  t1.start();  Thread.sleep(10);  flag = false;  System.out.println("main end");  }  
}

虽然很多人都是是指令重排序导致的,但是这里其实是因为Java编译器对线程内部的这段代码做了优化,他发现当前线程的flag是不会改变的,导致把while循环里的flag改成了true,导致程序无法退出。

解决什么问题

解决了在并发场景下,线程A修改的共享变量,线程B不可见的问题。

解决方案
  • 可以通过变量前用volatile修饰符修饰
  • 可以使用synchronized锁
  • 可以使用ReentrantLock锁,最后一定要finally中unlock
  • 使用final关键字,不可更改,所以不会出现不可见的情况
http://www.hskmm.com/?act=detail&tid=20926

相关文章:

  • C# Devexpress GridControl实现全选功能(转载,记录)
  • github Connection reset by 20.205.243.160 port 443 fatal: Could not read from remote repository.
  • VsCode Ai插件
  • 完整教程:基于完全分布式模式部署Hadoop(喂饭教程)
  • Vue 3.6 引入 Vapor Mode,虚拟DOM已死?
  • part 10
  • Nordic发布用于nRF54L系列的nRF Connect SDK裸机选项
  • 微软SSO集成中的顺序用户ID身份验证绕过漏洞剖析
  • content和text方法的区别
  • shell脚本动态域名解析阿里云
  • 聪明的wyk
  • Windows下进程和账户权限
  • Spring Gateway动态路由实现方案 - 详解
  • Nordic 高性能无线SoC nRF54LM20A,专为低功耗蓝牙与Matter设计
  • 调用setState 之后发生了什么?
  • element plus 配置主题色
  • Python教程:解决pip安装包时报错:error: externally-managed-environment This environment is externally managed
  • 哲学家进餐问题
  • 16.1 总体主成分分析
  • 黄金分割比
  • 借助Aspose.Email,使用 Python 读取 Outlook MSG 文件
  • 痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU启动那些事(11.B)- FlexSPI NOR连接方式大全(RT1180)
  • 文件同步工具深度测评(2025版):同步盘夺冠
  • Oracle故障处理:数据库启动时遇到ORA-01578错误
  • 【ACM出版|连续三届EI检索】第四届人工智能与智能信息处理国际学术会议(AIIIP 2025)
  • 【2025-09-28】平凡家庭
  • 实用指南:梦回童年,将JSNES 游戏模拟器移植到 HarmonyOS 移植指南
  • 单键触控感应芯片 电容是触控IC VKD233HS -永嘉微VINKA 原厂
  • 微算法科技(NASDAQ: MLGO)研发基于 DPoS 框架的 DL-DPoS(深度链接委托权益证明)机制,增强区块链的共识算法
  • JMM内存模型