Java并发 - (并发基础)

news2024/12/23 12:01:40

Java并发 - (并发基础)

1、什么是共享资源

  • 堆是被所有线程共享的一块内存区域。在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例

  • Java中几乎所有的对象实例都在这里分配内存。方法区与堆一样,也是各个线程共享的一块内存区域,它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。

  • 光看文字,会让我们觉得很抽象。如下图:

    image-20221116191523993

2、并发编程的难点

🤔 原子性问题

  • 操作系统做任务切换(CPU切换),可以发生在任何一条CPU指令执行完成后;
  • CPU能保证的原子操作是指令级别的,而不是高级语言的操作符(例如:n++)。
  • 如下图,是n++编译后,被编译CPU执行的指令。

image-20221116194015588

🧐 可见性问题

  • 可见性是指一个线程对共享变量的修改,另外一个线程能够立刻看到。
  • 可见性问题是由CPU的缓存导致的,多核CPU均有各自的缓存,这些缓存均要与内存进行同步。

image-20221116202546557

🧡 有序性问题

  • 在执行程序时。为了提高性能,编译器和处理器常常会对指令做重排序;
  • 重排序不会影响单线程的执行结果,但是在并发情况下,可能会出现诡异的BUG。
  • **参考地址:**https://zhuanlan.zhihu.com/p/298448987

3、JMM

💛 并发编程的关键目标

并发编程需要处理两个关键问题,即线程之间如何通信和同步。

  • **通信:**指线程之间以何种机制来交换信息;
  • **同步:**指程序中用于控制不同线程之间的操作发生的相对顺序的机制。

💜 并发编程的内存模型

共有两种并发编程模型:共享内存模型、消息传递模型,Java采用的是前者。

  • 在共享内存模型下,线程之间共享程序的公共状态,通过写-读内存中的公共状态进行隐式通信;
  • 在共享内存模型下,同步是显示进行的,程序员必须显示指定某段代码需要在线程之间互斥执行。

❣️ 这个内存模型:JMM

  • **参考地址:**https://javaguide.cn/java/concurrent/jmm.html#%E4%BB%8E-cpu-%E7%BC%93%E5%AD%98%E6%A8%A1%E5%9E%8B%E8%AF%B4%E8%B5%B7
  • **参考地址:**https://xie.infoq.cn/article/739920a92d0d27e2053174ef2
  • **参考地址:**http://concurrent.redspider.group/RedSpider.html

JMM 是Java Memory Model的缩写,Java线程之间的通信由 JMM 控制,即 JMM决定一个线程对共享变量的写入何时对另一个线程可见。JMM定义了线程和主内存之间的抽象关系,通过控制主内存与每个本地内存(抽象概念)之间的交互,JMM为Java程序员提供了内存可见性的保证。

image-20221116213852346

🔵 源代码与指令间的重排序

为了提高性能,编译器和处理器常常会对指令做重排序。重排序有3种类型,其中后2种都是处理器重排序。这些重排序可能会导致多线程程序出现内存可见性问题。

  1. **编译器优化重排序:**编译器在不改变单线程程序语义的前提下可以重新安排语句的执行顺序。
  2. **指令级并行重排序︰**现代处理器采用了指令级并行技术来将多条指令重叠执行,如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。
  3. **内存系统的重排序:**由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。

image-20221116214553907

🍉 重排序对可见性的影响

参考下图,虽然处理器执行的顺序是A1->A2,但是从内存角度来看,实际发生的顺序是A2->A1。这里的关键是,由于写缓冲区仅对自己的处理器可见,它会导致处理器执行内存操作的顺序可能会与实际的操作执行顺序不一致。由于现代的处理器都会使用写缓冲区,因此它们都会允许对写 - 读操作执行重排序。

image-20221116215014247

❓ 如何解决重排序带来的问题

对于编译器,JMM的编译器重排序规则会禁止特定类型的编译器重排序(比如volatile)。

对于处理器重排序,JMM的处理器重排序规则会要求编译器在生成指令序列时,插入特定类型的内存屏障(Memcry Barries /Memory Fence)指令,通过内存屏障指令来禁止特定类型的处理器重排序。
由于常见的处理器内存模型比JMM要弱, Java编译器在生成字节码时,会在执行指令序列的适当位置插入内存屏障来限制处理器的重排序。同时,由于各种处理器内存模型的强弱不同,为了在不同的处理器平台向程序员展示一个一致的内存模型,JMM在不同的处理器中需要插入的内存屏障的数量和种类也不同。

CPU内存屏障:

  • LoadLoad: 禁止读和读的重排序;
  • StoreStore:禁止写和写的重排序;
  • LoadStore:禁止读和写的重排序;
  • StoreLoad:禁止写和读的重排序。

Java内存屏障

public final class Unsafe {
public native void loadFerice();// LoadLoad + LoadStore
public native void storeFence();// StoreStore + LoadStore
public native void fullFence(); // loadFence() + storeFence() + StoreLoad
}

❓ happens-before

JMM使用happens-before规则来阐述操作之间的内存可见性,以及什么时候不能重排序。在JMM中。如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须要存在happens-before关系。换个角度来说.如果A happens-before B,则意味着A的执行结果必须对B可见,也就是保证跨线程的内存可见性。其中,前4条规则与程序员密切相关。

  • 1、程序顺序规则:一个线程中的每个操作, happens-before于该线程中的任意后续操作;
  • 2、volatile变量规则:对一个volatile域的写, happens-before于任意后续对这个volatile域的读;
  • 3、synchronized规则:对一个锁的解锁, happens-before于随后对这个锁的加锁;
  • 4、传递性:若A happens-before B,且B happens-before C,则A happens-before C;
  • 5、start()规则:若线程A执行Thread.start(),则线程A的start()操作happens-before于线程B中的任意操作;
  • 6、 join()规则︰若线程A执行ThreadB.join()并成功返回,那么线程B中的任意操作happens-before于线程A从ThreadB.join()的成功返回。

image-20221116224120601

4、Volatile

🍊 volatile的基本特性

  • 可见性:对一个volatile变量的读,总是能看到对这个volatile变量最后的写入;
  • 原子性:对任意单个volatile变量的读/写具有原子性,但类似vclatile++这种复合操作不具有原子性。

🍐 volatile的内存语义

  • 写内存语义:当写一个volatile变量时,JMM会把该线程本地内存中的共享变量的值刷新到主内存;
  • 读内存语义:当读一个volatile变量时,JMM会把该线程本地内存置为无效,使其从主内存中读取共享变量。

🥥 volatile的实现机制

为了实现volatile的内存语义,编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。内存屏障插入策略非常保守,但它可以保证在任意处理器平台,任意的程序中都能得到正确的volatile内存语义。

  • 在每个volatile写操作的前面插入一个StoreStore屏障;
  • 在每个volatile写操作的后面插入一个StoreLoad屏障;
  • 在每个volatile读操作的后面插入—个LoadLoad屏障;
  • 在每个volatile读操作的后面插入一个LoadStore屏障。

🥩 volatile与锁的对比

volatile仅仅保证对单个volatile变量的读/写具有原子性,而锁的互斥执行的特性可以确保对整个临界区代码的执行具有原子性。在功能上锁比volatile更强大,在可伸缩性和执行性能上volatile更有优势。

5、锁

锁的内存语义

  • 当线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中;
  • 当线程获取锁时,JMM会把该线程对应的本地内存置为无效。

锁的实现机制

  • synchronized:采用CAS + Mark Word实现。存在锁升级的情况;
  • Lock:采用CAS + volatile实现。存在锁降级的情况核心是AQS 。

image-20221117130555447

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

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

相关文章

Linux实用操作-----快捷键的使用(收藏系列)

推荐教程:Linux零基础快速入门到精通 ctrl c 强制停止 •Linux某些程序的运行,如果想要强制停止它,可以使用快捷键ctrl c •命令输入错误,也可以通过快捷键ctrl c,退出当前输入,重新输入 ctrl d 退出…

注意论文投稿风险,现投期刊会不会成为预警期刊呢?

中科院发布《国际预警期刊名单》 2021年12月31日,中国科学院文献情报中心期刊分区表团队发布《国际期刊预警名单(试行)》,用以提醒科研人员审慎选择成果发表平台,提示出版机构强化期刊质量管理。截至目前,…

Vue 实现拖拽模块(二)自定义拖拽组件位置

上文介绍了 拖拽添加组件 的简单实现,本文将继续给大家分享如何自定义拖拽组件位置的简单实现,文中通过示例代码介绍,感兴趣的小伙伴们可以了解一下 本文主要介绍了 Vue自定义拖拽组件位置的简单实现,具体如下: 效果图…

高空抛物检测方案设计(使用SOM进行轨迹分类)

文章目录前言一、技术方案介绍1.方案设计图2.流程介绍3.说明二、实际检测1.摄像头的安装2.实际检测三、误报解决误报事件1:飞鸟误报事件2:树叶误报事件3:被子解决方案轨迹展示原始轨迹SOM分类结果总结前言 高空抛物检测的关键是方案的设计&a…

MATLAB 绘图合集:分类散点图gscatter

本文主要介绍如何依据数据类别同时呈现数据散点图。 目录 说明 例子 使用默认设置绘图 使用数据类别来画图 使用多组数据类别来画图 创建并调整散点图 说明 gscatter(x,y,g) 创建 和 的散点图x,y按 分组g。输入x和 y是相同大小的向量。 例子 gscatter(x,y,g,c…

Jekyll 语句语法、功能的实现方法和结构介绍小手册

本文很长,建议使用侧边栏进行跳转。 本文虽然按照由浅入深的顺序介绍了 Jekyll 的语句语法和功能结构,但是主要用于快速查询一些 Jekyll 语句、功能的实现方法和结构介绍。 如果你想: 了解查看一些常用的 Jekyll 的相关命令和选项还请查看&…

第六章第一节:图的基本概念和存储及基本操作

文章目录1. 图的基本概念1.1 图逻辑结构的应用1.2 无向图,有向图1.3 简单图,多重图1.4 顶点的度,入度和出度1.5 顶点和顶点的关系描述1.6 连通图,强连通图1.7 研究图的局部——子图1.8 生成树1.9 生成森林1.10 边的权,…

手机怎么实现图片转文字操作?学会这三招就够了

随着互联网不断发展,我们手机的功能越来越丰富,现在基本上只需要一部手机,就能满足我们的多样化需求。比如想要提取书本中的文字,我们不需要再手动输入,只要将文字内容拍照下来,利用一些软件来提取图片中的…

【深度学习】argparse模块一些学习心得体会(2)| parser.parse_known_args() |位置参数 可选参数

文章目录前言一、位置参数和可选参数二、parser.parse_known_args()前言 之前我们写了一期命令行模块的使用介绍,但是依然有很多语法是没有介绍到的:比如parser.parse_known_args()这样的命令。这样的命令大量出现在各大开源项目中,今天我就…

外汇天眼:官网虚假宣传受到多重监管!FCA率先发出警告!

11月16日,英国金融行为监管局( FCA )发出最新警告,提示投资者警惕与 Trade Top FX 这家未经授权的公司打交道。 FCA警告称:Trade Top FX 在未经我们授权的情况下在英国提供金融服务或产品,如果一旦遭受资金损失,您将无…

Word处理控件Aspose.Words功能演示:在 Python 中比较两个 Word 文档

在各种情况下执行 Word 文档的比较以确定差异。各种在线工具允许您比较 Word 文档,但是,您可能需要在应用程序中实现比较功能。为实现它,本文展示了如何在 Python 中比较两个 Word 文档。 Aspose.Words for . Python 最新下载(qu…

子容器在启动期间失败

​ 遇错: 今天遇到一个Bug:A child container failed during start 中文翻译为:子容器在启动期间失败 事情是这样的,一开始我在做案例的时候使用的tomcat是本地集成的,项目能正常运行; 后来我将tomcat的…

Dopamine-PEG-N3,DOPA-PEG-azide,水溶性PEG试剂供应

1、名称 英文:Dopamine-PEG-N3,DOPA-PEG-azide 中文:多巴胺-聚乙二醇-叠氮 2、CAS编号:N/A 3、所属分类:Azide PEG Dopamine PEG 4、分子量:可定制,有2k、5k、3.4k、10k、20k、1k 5、质量…

【salesforce】Lightning Web Component Study Log —— Part 2

持续学习中… 文章目录版本管理V1.0.01. The Lightning Web Components Model1.1 Web演变1.2 LWC1.3Aura和LWC的互用性2. Creating Lightning Web Components2.1 在VSCode定义一个LWC组件2.2 文件构成2.3 客户端-服务端体系结构2.4 基础UI组件-JS2.5 基础UI组件-HTML2.6 基础UI…

艾美捷PEG-2000 DMG解决方案

艾美捷PEG-2000 DMG英文全名1,2-dimyristoyl-rac-glycero-3-methoxypolyethylene glycol-2000,中文名可对应翻译为二肉豆蔻酰甘油-聚乙二醇2000。它的分子式为C122H242O50,分子量2509.2(平均值),代表结构如下&#xff…

数字IC手撕代码-XX公司笔试真题(串并转换控制)

前言: 本专栏旨在记录高频笔面试手撕代码题,以备数字前端秋招,本专栏所有文章提供原理分析、代码及波形,所有代码均经过本人验证。 目录如下: 1.数字IC手撕代码-分频器(任意偶数分频) 2.数字…

JetsonNano部署yolo5 c++ onnx

编译OpenCV最新4.5.x版本 Jetson Nano自带的OpenCV版本比较低,Jetpack4.6对应的OpenCV版本为4.1的 而OpenCV当前最新版本已经到了4.5跟4.6了,4.5.x中OpenCV DNN支持了很多新的模型推理跟新的特性都无法在OpenCV4.1上演示,所以我决定从源码编…

Go语言 02

2.1 下载安装 Go Golang 中文网 Go 的安装也是十分的简洁、简单。就是 Next。哈哈 ~ 输入 go version 来查看是否安装完成吧 ~ 2.2 配置环境变量和工作目录 GOROOT:C:\Environment\Go 意味着 Go 在哪里。 在配置 GOPATH 之前,先把用户的 GOPATH 删掉。…

远程预付费电能管理系统在工业园的应用,主要功能有哪些?

安科瑞 李可欣 具体可咨询:Acrel_lkx 0概述 本项目为凌云工业园提供解决方案。本项目共有DDSY1352-NK/DTSY1352-NK预付费计量表41台,针对凌云工业园商业用电实现用电的智能化管理,通过安科瑞终端预付费电能表计来计量每个商铺的用电量&am…

web前端-html-css-background背景(color样式,image图片,repeat重复方式,position定位,简写)

背景 背景样式和背景图片重复方式 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title></title><style type"text/css">.box1 {width: 1024px;height: 724px;margin: 0 auto;/*设置背景样式*/backgr…