【Java回顾】Day5 并发基础|并发关键字|JUC全局观|JUC原子类

news2025/1/13 17:56:50

JUC全称java.util.concurrent 处理并发的工具包(线程管理、同步、协调)

一.并发基础

多线程要解决什么问题?本质是什么?

  • CPU、内存、I/O的速度是有极大差异的,为了合理利用CPU的高性能,平衡三者的速度差异,解决办法如下:
    • 计算机体系结构CPU增加了缓存,以均衡与内存的速度差异。//导致可见性问题
    • 操作系统增加了进行、线程,以分时复用CPU,进而均衡CPU与I/O设备的速度差异;//导致原子性问题。
    • 编译程序优化指令执行次序,使得缓存能够得到更加合理地利用。//导致有序性问题

(1)CPU增加缓存导致的可见性问题

  • 原因:CPU的计算速度远远大于内存的访问速度。因此,CPU引入了缓存(L1,L2,L3),线程运行时,数据通常会先加载到CPU缓存中,计算结束后再同步到贮存。
  • 可见性:不同线程可能运行在不同的CPU核心上,各自有独立的缓存。这导致线程在某些时刻无法及时感知其他线程对共享变量的修改。
  • 例子:修改主存的值,但是其他线程可能还在读取缓存的数值。

(2)操作系统增加进程、线程导致的原子性问题

  • 原因
    • 为了充分利用CPU资源,操作系统通过进程和线程来分时复用CPU,但在多线程环境下,线程切换可能打断对共享变量的修改,使得某些操作无法完整执行,破坏了操作的原子性。
  • 问题
    • 某些操作需要多个步骤完成,而线程切换可能在中间插入,导致共享数据处于不一致的状态。线程切换破坏了连续操作的完整性,现代CPU支持指令级并行和多核架构,线程切换可能使对共享资源的访问被中断。

(3) 编译指令优化导致的有序性问题

  • 原因:为了提升程序运行效率,编译器和CPU可能对指令执行顺序进行优化(指令重排序)。但这些优化可能导致程序在多线程环境下的执行顺序与代码的书写顺序不一致。
  • 问题:在多线程中,指令重排序可能导致线程看到的执行顺序与预期不符,从而破坏程序逻辑。

Java怎么解决并发问题的?

  • Java内存模型(java Memory Model)是个很复杂的规范,具体看Java内存模型详解

理解的第一个维度:核心知识点

  • JMM(Java Memory model)本质上可以理解为,规范了JVM如何提供按需禁用缓存和编译优化的方法。
  • 方法包括
    • volatile、synchronized和final三个关键字
    • Happens-Before规则

理解的第二个维度:原子性,有序性,可见性

原子性

  • 在Java中,对基本数据类型的变量的读取和赋值(数字赋值,变量之间的相互赋值不属于)属于原子性操作,这些操作不可被中断。要么执行,要么不执行。
  • 如果想实现更大范围操作的原子性,通过synchronized和Lock实现。因为这能够保证任一时刻只有一个线程执行该代码块,那么自然不存在原子性问题了。

可见性

  • volatile关键字
  • 当一个共享变量被volatile修饰时,会保证修改的值立即被更新到主存,当有其他线程需要读取时,会去内存中读取新值。
  • 通过synchronized和Lock实现,能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会对变量的修改刷新到主存当中,因此可以保证可见性。

有序性

  • volatile关键字
  • synchronized和Lock也可以,保证每个时刻只有一个线程执行同步代码,相当于是让线程顺序执行同步代码。JMM是通过Happens-Before规则来保证有序性的。

二、并发关键字 volatile和synchronized

1.volatile

  • 保证了不同线程对共享变量进行操作时的可见性,即一个线程修改了某个变量的值,这个新值对其他线程来说是立即可见的。
  • 禁止进行指令重排序
  • volatile不保证原子性

参考:https://note.youdao.com/ynoteshare/index.html?id=0a2692da5a11099e198dcfe179c3c655&type=note&_time=1736243887397

可见性问题详解

请添加图片描述

请添加图片描述

  • 过程
    • 每个线程从主内存中将变量拷贝到本地内存作为副本并操作变量副本
    • 写回主内存,会通过CPU总线嗅探机制告知其他线程该变量副本已经失效,需要重新从主内存中读取。
    • 总之,当一个线程修改了volatile修饰的变量,当修改后的变量写回内存时,其他线程能立即看到最新值。

2.synchronized

参考:https://note.youdao.com/ynoteshare/index.html?id=a9d1d098bc64bef9c3e458f0000d37d4&type=note&_time=1736245618633

  • 注意:volatile只能保证可见性和有序性,synchronized能保证可见性、有序性和原子性。

实现什么样类型的锁?

  • 悲观锁:每次访问共享资源时都会上锁
  • 非公平锁:线程获取锁的顺序并不一定是按照线程堵塞的顺序
  • 可重入锁:已经获取锁的线程可以再次获取锁
  • 独占锁或排他锁:该锁只能被一个线程所持有,其他线程均被堵塞。
  • 请添加图片描述

关键字的使用方式

  • 修饰普通同步方法
  • 修饰静态同步方法
  • 修饰同步方法块

3.CAS(Compare-And-Swap)

  • 无锁的并发操作,比较和交换,在高并发场景下进行线程安全的变量更新,避免了传统加锁操作中的堵塞问题。
  • 工作原理
    • CAS 操作需要三个值:
      • 内存值 V :当前变量的实际值。
      • 预期值 A :当前线程认为变量的期望值。
      • 新值 B :希望更新为的值。
    • 操作流程如下:
      • 如果 V == A,则将 V 更新为 B
      • 如果 V != A,说明变量已经被其他线程修改,当前线程放弃更新。
  • 存在三大问题
    • ABA问题
    • 不适用于竞争激烈的情形下
    • 只能保证一个共享变量的原子操作
  • 请添加图片描述

三、JUC全局观

请添加图片描述

  • Lock框架和Tools类
  • Collection 并发集合
  • Atomic 原子类
  • Executors 线程池

1.JUC原子类

  • java并发包(java.util.concurrent.atomic)提供的一组基于CAS(Compare-And-Swap)操作的线程安全类。对基本数据类型或对象的变量进行原子操作,而无需加锁,提供了一种高效的方式来实现线程安全。
  • 主要利用CAS(compare and swap)+volatile和native方法来保证原子操作,从而避免synchronized的高开销,执行效率大为提升。

分类

  • 基本类型原子类
    • AtomicInteger:对 int 类型变量进行原子操作。
    • AtomicLong:对 long 类型变量进行原子操作。
    • AtomicBoolean:对 boolean 类型变量进行原子操作。
  • 引用类型原子类
    • AtomicReference<T>:对引用对象进行原子操作。
    • AtomicStampedReference<T>:解决 CAS 的 ABA 问题,结合版本号进行原子操作。
    • AtomicMarkableReference<T>:通过布尔标记和引用值一起操作,解决特定场景的并发问题。
  • 数组原子类
    • AtomicIntegerArray:对 int 数组的元素进行原子操作。
    • AtomicLongArray:对 long 数组的元素进行原子操作。
    • AtomicReferenceArray<T>:对引用类型数组的元素进行原子操作。
  • 字段更新原子类(反射实现)
    • AtomicIntegerFieldUpdater:对类中 int 类型字段进行原子更新。
    • AtomicLongFieldUpdater:对类中 long 类型字段进行原子更新。
    • AtomicReferenceFieldUpdater:对类中引用类型字段进行原子更新。
  • 累加器
    • LongAdderDoubleAdder:对高并发场景下的累加操作进行优化。

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

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

相关文章

android framework.jar 在应用中使用

在开发APP中&#xff0c;有时会使用系统提供的framework.jar 来替代 android.jar, 在gradle中配置如下&#xff1a; 放置framework.jar 依赖配置 3 优先级配置 gradle.projectsEvaluated {tasks.withType(JavaCompile) {Set<File> fileSet options.bootstrapClasspat…

CHAIN OF RESPONSIBILITY(职责链)—对象行为型模式

1. 意图 使多个对象都有机会处理请求&#xff0c;从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链&#xff0c;并沿着这条链传递该请求&#xff0c;直到有一个对象处理它为止。 2. 动机 考虑一个图形用户界面中的上下文有关的帮助机制。用户在界面的任一部分…

Java高频面试之SE-11

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本牛马baby今天又来了&#xff01;哈哈哈哈哈嗝&#x1f436; Java中是引用传递还是值传递&#xff1f; 在 Java 中&#xff0c;方法参数传递是通过 值传递 的方式实现的&#xff0c;但这可能会引起一…

VsCode对Arduino的开发配置

ps&#xff1a;我的情况是在对esp32进行编译、烧录时&#xff0c;找不到按钮&#xff0c;无法识别Arduino文件&#xff0c;适合已经有ini文件的情况。 1.在vscode中安装拓展 2.打开设置&#xff0c;点击右上角&#xff0c;转到settings.json文件 3.复制以下代码并保存 {"…

Apache Hop从入门到精通 第一课 揭开Apache Hop神秘面纱

一、Apache Hop是什么&#xff1f; 1、Apache Hop&#xff0c;简称Hop&#xff0c;全称为Hop Orchestration Platform&#xff0c;即Hop 工作编排平台&#xff0c;是一个数据编排和数据工程平台&#xff0c;旨在促进数据和元数据编排的所有方面。Hop让你专注于你想要解决的问题…

模拟SpringIOCAOP

一、IOC容器 Ioc负责创建&#xff0c;管理实例&#xff0c;向使用者提供实例&#xff0c;ioc就像一个工厂一样&#xff0c;称之为Bean工厂 1.1 Bean工厂的作用 先分析一下Bean工厂应具备的行为 1、需要一个获取实例的方法&#xff0c;根据一个参数获取对应的实例 getBean(…

基于ILI9341液晶屏+STM32U5单片的显示试验

试验要求&#xff1a; 1、通过串口&#xff0c;下发两个命令 STR和PIC&#xff1b; 2、STR模式&#xff1a; &#xff08;1&#xff09;串口输入什么&#xff0c;屏幕上显示什么 &#xff08;2&#xff09;如果屏幕满&#xff0c;自动下滚 &#xff08;3&#xff09;输入回车&a…

Elasticsearch:向量数据库基础设施类别的兴衰

过去几年&#xff0c;我一直在观察嵌入技术如何从大型科技公司的 “秘密武器” 转变为日常开发人员工具。接下来发生的事情 —— 向量数据库淘金热、RAG 炒作周期以及最终的修正 —— 教会了我们关于新技术如何在更广泛的生态系统中找到一席之地的宝贵经验。 更多有关向量搜索…

《系统爆破:MD5易破,后台登录可爆破?》

声明&#xff1a;笔记的只是方便各位师傅学习知识&#xff0c;以下代码、网站只涉及学习内容&#xff0c;其他的都与本人无关&#xff0c;切莫逾越法律红线&#xff0c;否则后果自负。 爆破Sales系统 一、爆破MD5 场景&#xff1a;已知MD5的加密字符串&#xff0c;如何得知明…

《Spring Framework实战》14:4.1.4.5.自动装配合作者

欢迎观看《Spring Framework实战》视频教程 自动装配合作者 Spring容器可以自动连接协作bean之间的关系。您可以通过检查ApplicationContext的内容&#xff0c;让Spring自动为您的bean解析协作者&#xff08;其他bean&#xff09;。自动装配具有以下优点&#xff1a; 自动装配…

GitLab CI/CD使用runner实现自动化部署前端Vue2 后端.Net 7 Zr.Admin项目

1、查看gitlab版本 建议安装的runner版本和gitlab保持一致 2、查找runner 执行 yum list gitlab-runner --showduplicates | sort -r 找到符合gitlab版本的runner&#xff0c;我这里选择 14.9.1版本 如果执行出现找不到下载源&#xff0c;添加官方仓库 执行 curl -L &quo…

冒泡排序基础与实现

目录 1. 原理图 ​编辑 2. 什么是冒泡排序 3. 工作原理 3.1 具体步骤 3.2 时间复杂度 3.3 空间复杂度 4. 代码实现 5. 总结 1. 原理图 2. 什么是冒泡排序 冒泡排序&#xff08;Bubble Sort&#xff09;是一种简单的排序算法&#xff0c;它通过重复地遍历要排序的列表&am…

acwing_5722_十滴水

acwing_5722_十滴水 下面这篇大佬的题解属实是把指针用明白了&#xff0c;可以好好理解一下&#xff1a; 原题解连接&#xff1a;AcWing 5722. 一个简单模拟实现 - AcWing map/unordered_map的用法:见收藏夹 #include<iostream> #include<unordered_map> #incl…

【AI进化论】 AI微信机器人 | sealos + 智能微秘书 打造AI机器人 | 智能微秘书配置教程

一、sealos 什么是sealos &#xff1f; One cloud OS for all applications 1、创建sealos账号密码 根据链接&#xff08;帮我凑点sealos使用额度感谢&#xff09;&#xff1a;https://cloud.sealos.run/?uidXfUpoQk92c 登录后如下页面&#xff1a; 2、创建应用 点击【应…

Agentless:OpenAI 采用的非代理框架

不需要代理库来解决复杂的业务问题。Agentless 是OpenAI采用的非代理框架&#xff0c;用于在 o3 的 SWE Bench 上实现最高精度。SWE-bench 是 github的真实软件工程问题基准。Agentless 遵循简单的三阶段流程&#xff1a;本地化、修复和补丁验证&#xff1a; 1 ⃣生成存储库的…

Model-based RL自动出价算法的演进之路

▐ 导读 近年来&#xff0c;强化学习自动出价算法已成为智能投放领域的标志性技术&#xff0c;然而其所存在的在离线不一致、线上数据覆盖空间受限等关键问题尚未被完全解决。在本文中&#xff0c;我们提出一种Model-based RL&#xff08;MBRL&#xff09;自动出价算法训练新范…

【Cocos TypeScript 零基础 7.1】

目录 重写 小结一下心得页面跳转背景移动精简 player敌机精灵 重写 小结一下心得 本人重写了整个项目 有了点小心得 页面跳转 director.loadScene(s2)背景移动 canvas 是画布 为什么要向上图布局? 方便计算相对坐标,脚本还是只写一个 绑定上 BG 一样跑,不影响 export cl…

鸿蒙UI(ArkUI-方舟UI框架)

参考&#xff1a;https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V13/arkts-layout-development-overview-V13 ArkUI简介 ArkUI&#xff08;方舟UI框架&#xff09;为应用的UI开发提供了完整的基础设施&#xff0c;包括简洁的UI语法、丰富的UI功能&#xff…

禅道使用实践(2)-产品篇

前言 本文目的皆在指导产品团队使用禅道基于实操完成产品&#xff0c;项目的创建&#xff0c;需求汇总&#xff0c;版本规划&#xff0c;以及验收发布的基本流程。希望能帮助到首次使用禅道而不知道从何下手的团队。 基本概念 此章节内容与我上一篇的开发篇相同&#xff0c;从…

js逆向说明

一 负载的内容传输用这个格式 Content-Type: multipart/form-data Content-Type 是 HTTP 请求头中的一个字段&#xff0c;它告诉服务器请求体的类型。在这个例子中&#xff0c;Content-Type 的值为 multipart/form-data&#xff0c;这表示请求体采用了 multipart/form-data 格…