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

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:对高并发场景下的累加操作进行优化。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

自然语言转 SQL:通过 One API 将 llama3 模型部署在 Bytebase SQL 编辑器

使用 Open AI 兼容的 API&#xff0c;可以在 Bytebase SQL 编辑器中使用自然语言查询数据库。 出于数据安全的考虑&#xff0c;私有部署大语言模型是一个较好的选择 – 本文选择功能强大的开源模型 llama3。 由于 OpenAI 默认阻止出站流量&#xff0c;为了简化网络配置&#…

一学就废|Python基础碎片,文件读写

文件处理是指通过编程接口对文件执行诸如创建、打开、读取、写入和关闭等操作的过程。它涉及管理程序与存储设备上的文件系统之间的数据流&#xff0c;确保数据得到安全高效的处理。 Python 中的文件模式 打开文件时&#xff0c;我们必须指定我们想要的模式&#xff0c;该模式…

牛客网刷题 ——C语言初阶(6指针)——倒置字符串

1. 题目描述&#xff1a;倒置字符串 牛客网OJ题链接 描述 将一句话的单词进行倒置&#xff0c;标点不倒置。比如 I like beijing. 经过函数后变为&#xff1a;beijing. like I 输入描述&#xff1a; 每个测试输入包含1个测试用例&#xff1a; I like beijing. 输入用例长度不超…

YOLOv10改进,YOLOv10自研检测头融合HyCTAS的Self_Attention自注意力机制+添加小目标检测层(四头检测)+CA注意机制,全网首发

摘要 论文提出了一种新的搜索框架,名为 HyCTAS,用于在给定任务中自动搜索高效的神经网络架构。HyCTAS框架结合了高分辨率表示和自注意力机制,通过多目标优化搜索,找到了一种在性能和计算效率之间的平衡。 理论介绍 自注意力(Self-Attention)机制是HyCTAS框架中的一个重…

Web前端界面开发

前沿&#xff1a;介绍自适应和响应式布局 自适应布局&#xff1a;-----针对页面1个像素的变换而变化 就是我们上一个练习的效果 我们的页面效果&#xff0c;随着我们的屏幕大小而发生适配的效果&#xff08;类似等比例&#xff09; 如&#xff1a;rem适配 和 vw/vh适配 …

机器学习05-最小二乘法VS梯度求解

机器学习05-最小二乘法VS梯度求解 文章目录 机器学习05-最小二乘法VS梯度求解0-核心知识点梳理1-最小二乘法和梯度求解算法什么关系最小二乘法梯度求解算法两者的关系 2-最小二乘法可以求解非线性回归吗3-最小二乘法不使用梯度求解算法&#xff0c;给出一个简单的示例&#xff…

maven的简单介绍

目录 1、maven简介2、maven 的主要特点3、maven的下载与安装4、修改配置文件5、私服(拓展) 1、maven简介 Maven 是一个广泛使用的项目管理和构建工具&#xff0c;主要应用于 Java 项目。Maven 由 Apache 软件基金会开发和维护&#xff0c;它提供了一种简洁且一致的方法来构建、…

C++ 基础思维导图(三)异常-STL

1、异常 异常举例 BankAccount.h #ifndef BANK_ACCOUNT_H #define BANK_ACCOUNT_H#include <iostream> #include <stdexcept>class InsufficientFundsException : public std::runtime_error { public:InsufficientFundsException() : std::runtime_error("I…

【C++入门】详解(中)

目录 &#x1f495;1.函数的重载 &#x1f495;2.引用的定义 &#x1f495;3.引用的一些常见问题 &#x1f495;4.引用——权限的放大/缩小/平移 &#x1f495;5. 不存在的空引用 &#x1f495;6.引用作为函数参数的速度之快&#xff08;代码体现&#xff09; &#x1f4…

人工智能之数学基础:函数间隔和几何间隔

本文重点 在机器学习领域,尤其是支持向量机(SVM)算法中,函数间隔(Functional Margin)和几何间隔(Geometric Margin)是两个至关重要的概念。它们不仅用于描述数据点到超平面的距离,还直接影响到分类器的性能与泛化能力。本文将详细介绍这两个概念,并探讨它们之间的区…

UE5 打包项目

UE5 打包项目 flyfish 通过 “文件”->“打开项目”&#xff0c;然后在弹出的对话框中选择项目文件&#xff08;通常是以.uproject为后缀的文件&#xff09; 选择目标平台&#xff1a; 在 UE5 主界面中&#xff0c;找到 “平台”&#xff08;Platforms&#xff09;。根据…

.NET framework、Core和Standard都是什么?

对于这些概念一直没有深入去理解&#xff0c;以至于经过.net这几年的发展进化&#xff0c;概念越来越多&#xff0c;越来越梳理不容易理解了。内心深处存在思想上的懒惰&#xff0c;以为自己专注于Unity开发就好&#xff0c;这些并不属于核心范畴&#xff0c;所以对这些概念总是…

《python》——jieba库

jieba库 jieba简介 jieba 是一个非常受欢迎的中文分词库 中文分词&#xff1a;这是 jieba 库最主要的功能。它能够将一段中文文本按照词语进行切分。例如&#xff0c;对于句子 “我爱自然语言处理”&#xff0c;jieba 分词后可以得到 [“我”, “爱”, “自然语言”, “处理”…

实训云上搭建集群

文章目录 1. 登录实训云1.1 实训云网址1.2 登录实训云 2. 创建网络2.1 网络概述2.2 创建步骤 3. 创建路由器3.1 路由器名称3.1 创建路由器3.3 查看网络拓扑 4. 连接子网5. 创建虚拟网卡5.1 创建原因5.2 查看端口5.3 创建虚拟网卡 6. 管理安全组规则6.1 为什么要管理安全组规则6…

python-42-使用selenium-wire爬取微信公众号下的所有文章列表

文章目录 1 seleniumwire1.1 selenium-wire简介1.2 获取请求和响应信息2 操作2.1 自动获取token和cookie和agent2.3 获取所有清单3 异常解决3.1 请求url失败的问题3.2 访问链接不安全的问题4 参考附录1 seleniumwire Selenium WebDriver本身并不直接提供获取HTTP请求头(header…

【理论】测试框架体系TDD、BDD、ATDD、MBT、DDT介绍

一、测试框架是什么 测试框架是一组用于创建和设计测试用例的指南或规则。框架由旨在帮助 QA 专业人员更有效地测试的实践和工具的组合组成。 这些指南可能包括编码标准、测试数据处理方法、对象存储库、存储测试结果的过程或有关如何访问外部资源的信息。 A testing framewo…

详细全面讲解C++中重载、隐藏、覆盖的区别

文章目录 总结1、重载示例代码特点1. 模板函数和非模板函数重载2. 重载示例与调用规则示例代码调用规则解释3. 特殊情况与注意事项二义性问题 函数特化与重载的交互 2. 函数隐藏&#xff08;Function Hiding&#xff09;概念示例代码特点 3. 函数覆盖&#xff08;重写&#xff…

计算机系统组成(计算机组成原理 基础)

文章目录&#xff1a; 一&#xff1a;体系结构 1.系统组成 1.1 硬件系统 1.2 软件系统 2.工作原理 2.1 冯诺依曼体系 2.2 指令和指令系统 3.性能指标 二&#xff1a;硬件系统 1.主机 1.1 CPU 1.2 内存 2.外设 2.1 外存 2.2 输入设备 2.3 输出设备 2.4 适配器 …

STM32 : 波特率发生器

波特率发生器 1. 发送器和接收器的波特率 波特率寄存器 (BRR): 在串行通信中&#xff0c;发送器和接收器的波特率是由波特率寄存器&#xff08;BRR&#xff09;中的一个值 DIV 来确定的。 2. 计算公式 计算公式: 详细解释 1. 波特率寄存器 (BRR) BRR: 波特率寄存器是一…

全新市场阶段, Plume 生态不断壮大的 RWAfi 版图

加密市场在 2024 年迎来了新的里程碑。BTC 不仅成功推出 ETF&#xff0c;以 BTC 为代表的主流加密货币还在一系列传统金融机构的推动下逐步与主流金融市场接轨。与此同时&#xff0c;随着特朗普成功当选下一任美国总统&#xff0c;他承诺推出一系列友好的加密政策&#xff0c;并…