java并发编程的艺术【三】-【一】java内存模型基础

本文深入探讨并发编程中的两大核心问题:线程间通讯及线程同步。详细介绍了Java采用的共享内存模型进行线程间通讯的方式,以及JVM如何控制本地内存与主内存之间的交互以确保内存可见性。此外,还讨论了编译器和处理器对指令的重排序对并发编程的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

并发编程的两个关键问题
1,并发编程中需要处理两个关键的问题,第一个是线程之间的通讯, 通讯是指的是线程之间如何交换信息,在命令式的编程中,线程之间的通讯有两种方式:共享内存和消息传递。
2,第二个问题是线程同步,同步指的是程序中用于控制不同线程间的操作发生相对顺序的机制。

java采用的是共享内存模型进行线程间的通讯,在共享内存模型下,同步是显式的进行的,程序员必须显式的指定方法或者代码块之间的互斥关系(锁机制)。

java内存模型的抽象结构:
java中,所有的实例域、静态域、数组都存储在堆内存中,堆内存在线程之间是共享的,也就是抽象模型中的【主内存】,局部变量、方法参数定义和异常处理器不会共享【本地内存】,不涉及内存可见性的问题。

这里写图片描述

在抽象内存模型中,定义了主内存、本地内存、线程三者之间的关系。其中JVM控制着本地内存和主内存之间的交互。

假设线程A和B之间要通讯,一定会经过下面的过程
1,线程A把本地副本刷新到主内存中。
2,jvm设置B线程的本地副本中的变量失效。
3,线程B读取主内存中的变量到本地内存。

jvm就是控制本地内存与主内存之间的交互为程序员提供的内存可见性。

从源代码到指令序列的重排序
执行程序的时候,为了提高性能,编译器和处理器常常会对指令做重排序,重排序分为三种类型。
1,编译器优化的重排序
2,指令级并行的重排序
3,内存系统的重排序

这里写图片描述

jvm通过禁止特定类型的编译器重排序和处理器的重排序,为程序员提供一定的内存可见性。

并发编程模型的分类
现代的处理器都会有写缓冲区来临时保存要写的数据, 相当于把要写的数据队列放在一个缓冲区中, 不影响和堵塞别的读指令操作,写缓冲区有很多好处,但是会带来内存可见性的问题。

假设有两个处理器,一定要注意是两个处理器,不是两个线程。做如下工作的时候。

这里写图片描述

期待的结果当然是x=2 y=1,但是我们可能会得到的结果是x=y=0,原因如下:
这里写图片描述

在写缓冲区没有写的时候,读操作已经执行完成,关键原因是写缓冲区仅仅对自己的处理器可见。

为了保证内存的可见性,java编译器在生成指令序列的时候回插入内存屏障来禁止特定类型的指令重排序,内存指令分为四类:
这里写图片描述

可能表格看起来不舒服,也不好记住
提供一个方法:
java中的内存访问分为两种,一种的是写,也就是刷新到内存[store], 第二种是读,也就是装载[load]。
屏障的类型是有load 和 store组合成的 , 例如load1; loadstore;store2的解释是确保load1先于store2装载,也先于store2后面的指令存储。 第一个字母load 指的是load1和store2的先后顺序, 后面的store指的是load1和load2之后指令集的先后关系。了解这个规律就不怕忘记了。

从上面的图上可以看出StoreLoad是一个全能型的屏障,包含了上面三个屏障的功能。

Happens-before规则
从jdk5开始,java使用的是jsr-133内存模型,jsr-133模型使用happens-before概念阐述内存的可见性。
happens-before规则:
1,程序顺序原则: 在一个线程中,前面的代码happens-before于后面的代码。
2,监视器锁原则: 对于一个锁的解锁happens-before于随后对这个锁的加锁。
3,volatile变量规则: 对于一个volatile域的写happens-before语后续对这个域的读
4,传递性原则:Ahappens-beforeB, Bhappens-beforeC 则Ahappens-beforeC

需要注意的是happens-before规则并不是指的是前一个操作必须早后一个操作之前执行,而是指的是前一个操作必须对后一个操作可见。

资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在当今的软件开发领域,自动化构建与发布是提升开发效率和项目质量的关键环节。Jenkins Pipeline作为种强大的自动化工具,能够有效助力Java项目的快速构建、测试及部署。本文将详细介绍如何利用Jenkins Pipeline实现Java项目的自动化构建与发布。 Jenkins Pipeline简介 Jenkins Pipeline是运行在Jenkins上的套工作流框架,它将原本分散在单个或多个节点上独立运行的任务串联起来,实现复杂流程的编排与可视化。它是Jenkins 2.X的核心特性之,推动了Jenkins从持续集成(CI)向持续交付(CD)及DevOps的转变。 创建Pipeline项目 要使用Jenkins Pipeline自动化构建发布Java项目,首先需要创建Pipeline项目。具体步骤如下: 登录Jenkins,点击“新建项”,选择“Pipeline”。 输入项目名称和描述,点击“确定”。 在Pipeline脚本中定义项目字典、发版脚本和预发布脚本。 编写Pipeline脚本 Pipeline脚本是Jenkins Pipeline的核心,用于定义自动化构建和发布的流程。以下是个简单的Pipeline脚本示例: 在上述脚本中,定义了四个阶段:Checkout、Build、Push package和Deploy/Rollback。每个阶段都可以根据实际需求进行配置和调整。 通过Jenkins Pipeline自动化构建发布Java项目,可以显著提升开发效率和项目质量。借助Pipeline,我们能够轻松实现自动化构建、测试和部署,从而提高项目的整体质量和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

专注网赚的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值