【Java并发编程的艺术3】Java内存模型(上)

news2024/11/28 4:35:55

文章目录

    • Java内存模型的基础
      • 并发编程模型的两个关键问题
        • 通信
        • 同步
      • Java内存模型的抽象结构
      • 并发编程模型的分类
      • happens-before简介

Java内存模型的基础

并发编程模型的两个关键问题

在并发编程中,需要处理两个关键问题:线程之间如何通信以及线程之间如何同步

通信

线程之间以何种机制来交换信息。在命令式编程中,线程之间的通信机制有两种:共享内存和消息传递

共享内存的并发模型里,线程之间共享程序的公共状态,通过写-读内存中的公共状态进行隐式通信。在消息传递的并发模型里,线程之间没有公共状态,线程之间必须通过发送消息来显式进行通信

同步

程序中用于控制不同线程间操作发生相对顺序的机制。在共享内存并发模型里,同步是显式进行的。程序员必须显式指定某个方法或某段代码需要在线程之间互斥执行。在消息传递的并发模型里,由于消息的发送必须在消息的接收之前,因此同步是隐式进行的。

Java的并发采用的是共享内存模型,Java线程之间的通信总是隐式进行,整个通信过程对程序员完全透明。

Java内存模型的抽象结构

在Java中,所有实例域、静态域和数组元素都存储在堆内存(共享变量)中,堆内存在线程之间共享(后文将用“共享变量”这个术语代指实例域,静态域和数组元素)。局部变量、方法定义参数和异常处理器参数不会在线程之间共享,它们不会有内存可见性问题,也不受内存模型的影响。

Java线程之间的通信Java内存模型(后文简称为JMM)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见。线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存,本地内存中存储了该线程以读/写共享变量的副本。

Java内存模型的抽象示意如下图所示:

在这里插入图片描述

如上图所示,如果线程A与线程B之间要通信的话,必须要经历下面2个步骤

  1. 线程A把本地内存A中更新过的共享变量刷新到主内存中去。
  2. 线程B到主内存中去读取线程A之前已更新过的共享变量。

通过下图示意图来说明这两个步骤:

在这里插入图片描述

本地内存A和本地内存B由主内存中共享变量x的副本。假设初始时,这三个内存中的x值都是0。线程A在执行时,把更新后的x值(假设值为1)临时存放在自己的本地内存A中。当线程A和线程B需要通信时,线程A首先会把自己本地内存中修改后的x值刷新到主内存中,此时主内存中的x值变为了1。随后,线程B到主内存中去读取线程A更新后的x值,此时线程B的本地内存的x值也变为了1。

JMM通过控制主内存与每个线程的本地内存之间的交互,来为Java程序员提供内存可见性保证。

并发编程模型的分类

现代的处理器使用写缓冲区临时保存向内存写入的数据。写缓冲区可以保证指令流水线持续运行,它可以避免由于处理器停顿下来等待向内存写入数据而产生的延迟。同时,通过以批处理的方式刷新写缓冲区,以及合并写缓冲区中对同一内存地址的多次写,减少对内存总线的占用。

虽然写缓冲区有这么多好处,但每个处理器上的写缓冲区,仅仅对它所在的处理器可见。这个特性会对内存操作的执行顺序产生重要的影响:处理器对内存的读/写操作的执行顺序,不一定与内存实际发生的读/写顺序一致。

为了具体说明,请看下表

Process AProcess B
a = 1; // A1
x = b; //A2
b = 2; //B1
y = a; //B2

初始状态:a = b = 0;。处理器允许执行后得到结果:x = y = 0;

假设处理器A和处理器B按程序的顺序并行执行内存访问,最终可能得到x = y = 0的结果。具体原因如下所示:

在这里插入图片描述

这里处理器A和处理器B可以同时把共享变量写入自己的写缓冲区(A1,B1),然后从内存中读取另一个共享变量(A2,B2),最后才把自己写缓存区中保存的脏数据刷新到内存中(A3,B3)。

为了保存内存可见性,Java编译器在生成指令序列的适当位置会插入内存屏障指令来禁止特定类型的处理器重排序。

屏障类型指令示例说明
LoadLoad BarriesLoad1; LoadLoad; Load2确保Load1数据的装载先于Load2及所有后续装载指令的装载。
StoreStore BarriesStore1; StoreStore; Store2确保Store1数据对其他处理器可见(刷新到内存)先于Store2及所有后续存储指令的存储。
LoadStore BarriesLoad1; LoadStore; Store2确保Load1数据装载先于Store2及所有后续的存储指令刷新到内存。
StoreLoad BarriesStore1; StoreLoad; Load2确保Store1数据对其他处理器变得可见(刷新到内存)先于Load2及所有后续装载指令的装载。

happens-before简介

与程序员密切相关的happens-before规则如下;

  • 程序顺序规则:一个线程中的每个操作,happens-before于该线程中的任意后续操作。
  • 监视器锁规则:对一个锁的解锁,happens-before于随后对这个锁的加锁。
  • volatile变量规则:对一个volatile域的写,happens-before于任意后续对这个volatile域的读。
  • 传递性:如果A happens-before B,且B happens-before C,那么A happens-before C。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2189655.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript 中最快的循环是什么?

无论使用哪种编程语言,循环都是一种内置功能。JavaScript 也不例外,它提供了多种实现循环的方法,偶尔会给开发人员带来困惑:哪一种循环才是最快的? 以下是Javascript中可以实现循环的方法: For Loop While …

【GEE学习第三期】GEE常用函数总结

【GEE学习第三期】GEE常用函数总结 数据统计类ee.List.sequence函数 图像处理类ee.Geometry类‌defaultVisualizationVis函数 数据输入输出数值与绘图导出影像 参考 数据统计类 ee.List.sequence函数 用法如下: ee.List.sequence (开始,结…

FFT 分析进阶-笔记

FFT 分析进阶 边界不连续与泄漏效应解决方法增加窗函数海宁窗与哈布什窗混叠效应频率高到什么程度会出现混叠现象呢?那我们有办法去应对这个混叠吗?经典平均指数平均关于结果的显示模式FFT计算的三个常见的范例计算FFT图谱中某一段的总值,图中…

已解决:ValueError: Shape of passed values is (1509, 1), indices imply (1509, 2)

已解决:ValueError: Shape of passed values is (1509, 1), indices imply (1509, 2) 文章目录 写在前面问题描述报错原因分析: 解决思路解决办法1. 确认并调整数据的形状2. 使用 pd.concat() 或 pd.merge() 时检查数据3. 确保赋值时数据的形状匹配4. 重…

《PMI-PBA认证与商业分析实战精析》第7章 解决方案评价

第7章 解决方案评价 本章主要内容: 评价的建议思维 解决方案的评价计划 确定评价什么 何时以及如何验证解决方案的结果 评价验收标准和解决缺陷 促进通过/不通过的决策 获得解决方案的签字确认 评价解决方案的长期绩效 解决方案替换/淘汰 本章涵盖的考试…

DT高清车牌识别摄像机 任意文件读取

0x01 产品描述: DT-高清 车牌识别摄像机是一款先进的安防设备,采用高清图像传感器和先进的识别算法,能够精准、快速地识别车牌信息。其高清晰该摄像机结合了智能识别技术,支持实时监宴图像质量确保在各种光照和天气条件下都能准确…

多模态—图文匹配

可能最近大家已经发现了chatgpt可以根据自己的描述生成图片,其实这就是一个图文匹配的问题,可以理解为这是一个多模态的问题。 在模型训练时我们需要N个图片和N个文本对进行训练,文本通过text encoder形成文本语义向量,text enco…

MIT6.824--入门介绍

分布式系统的定义 分布式系统是指将多部各自拥有内存与时钟等硬件设备的独立的计算机系统以网络汇集起来,彼此之间仅仅通过网络消息传递进行通信和协调,共同对外提供服务,但对于系统的用户来说,就像是一台计算机在提供服务一样。…

SQL专项练习第二天

在数据处理和分析中,Hive 是一个强大的工具。本文将通过五个 Hive 相关的问题展示其在不同场景下的应用技巧。 先在home文件夹下建一个hivedata文件夹,把我们所需的数据写成txt文件导入到/home/hivedata/文件夹下面。 一、找出连续活跃 3 天及以上的用户…

随时随地,轻松翻译:英汉互译软件的便捷之旅

翻译英汉互译工具,就如同一位随时待命的语言助手,在这纷繁复杂的语言世界中为我们搭建起理解与沟通的桥梁。接下来,让我们一同深入了解这些神奇的英汉互译工具,探索它的诸多功能和独特魅力。 1.福晰在线翻译 链接直达>>h…

柔性数组 初学版

1.定义 结构中的最后⼀个元素允许是未知⼤⼩的数组,这就叫做『柔性数组』成员 有些编译器会报错⽆法编译可以改成: typedef struct st_type { int i; int a[]; // 柔性数组成员 }type_a; 2.柔性数组的特点: • 结构中的柔性数组成员前…

毕业设计_基于springboot+layui+mybatisPlus的中小型仓库物流管理系统源码+SQL+教程+可运行】41004

毕业设计_基于springbootlayuimybatisPlus的中小型仓库物流管理系统源码SQL教程可运行】41004 下载地址: https://download.csdn.net/download/qq_24428851/89843203 技术栈 后端:springboot、mybatis-plus、shiro 前端:layUI 存储&…

德国法院允许非营利组织LAION抓取受版权保护的图像用于AI训练

在人工智能快速发展的今天,一场发生在德国汉堡的法庭裁决为AI训练数据的收集和使用带来了新的讨论。这起案件不仅引发了公众对AI与版权之间关系的深思,也为未来AI发展的法律框架提供了重要参考。 事件的起因是非营利组织LAION在未经授权的情况下&#x…

SpringBoot日志打印实践

背景 在项目当中,我们经常需要打印一些日志埋点信息,这些日志埋点信息,在后续软件的运维、稳定性建设中发挥了巨大的作用: 问题追踪:通过埋点日志中的关键信息,帮助定位系统异常原因系统监控:…

《Linux从小白到高手》理论篇:Linux用户和组相关的命令

List item 本篇介绍Linux用户和组相关的命令,看完本文,有关Linux用户和组相关的常用命令你就掌握了99%了。Linux用户和组相关的命令可以分为以下六类: 一.用户和用户组相关查询操作命令: Id id命令用于显示用户的身份标识。常见…

解表之紫苏

** 声明:本文介绍的中药仅供学习使用,请勿擅自使用,否则后果自负!!!因水平有限,如有不当之处,请批评指正!!!!图片来源网络&#xff0…

No.1 | 从小白到入门:我的渗透测试笔记

嘿,小伙伴们!好久不见啊,是不是都以为我失踪了?😂 其实呢,最近一直在埋头苦学,感觉自己就像是在技术的海洋里游泳,每天都在吸收新知识。现在终于有时间冒个泡,跟大家分享…

Linux进程控制(2)(进程程序替换1)

目录 续--上一章 1.WIFEXITED && WEXITSTATUS 2.非阻塞等待 进程程序替换 1.先观代码 && 现象 2.原理解释 3.将代码改成多进程版 4.使用所有的替换方法,并且认识函数参数的含义 续--上一章 1.WIFEXITED && WEXITSTATUS 若需要知道退…

ODX相关基础知识普及

一、ODX概述 1.1 背景与意义 介绍汽车电子化的发展 随着科技的飞速发展,汽车电子化已成为现代汽车工业的重要趋势。从早期的机械控制到现代的电子控制,汽车电子化经历了巨大的变革。早期,汽车的主要控制系统都是基于机械原理,通…

Cisco ACI Simulator 6.0(7e)M 发布下载,新增功能简介

Cisco ACI Simulator 6.0(7e)M - ACI 模拟器 Application Centric Infrastructure (ACI) Simulator Software 请访问原文链接:https://sysin.org/blog/cisco-acisim-6/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.…