当前位置: 首页 > news >正文

java并发

基本概念

  • 并发编程可以抽象成三个核心问题: 分工、同步/协作、互斥

分工

将当前 Sprint 的 Story 拆分成「合适」大小的 Task,并且安排给「合适」的 Team Member 去完成

拆分的粒度太粗,导致这个任务完成难度变高,耗时长,不易与其他人配合;拆分的粒度太细,又导致任务太多,不好管理与追踪,浪费精力和资源。

关于分工,常见的 Executor,生产者-消费者模式,Fork/Join 等,这都是分工思想的体现

同步/协作

一个线程执行完任务,如何通知后续线程执行?

Java SDK 中 CountDownLatch 和 CyclicBarrier 就是用来解决线程协作问题的

互斥

互斥:同一时刻,只允许一个线程访问共享变量。分工和同步强调的是性能,但是互斥是强调正确性

当多个线程同时访问一个共享变量/成员变量时,就可能发生不确定性,造成不确定性主要是有可见性、原子性、有序性这三大问题,而解决这些问题的核心就是互斥

三大问题

可见性

定义: 一个线程对共享变量的修改,另外一个线程能够立刻看到,我们称为可见性

Java 内存模型规定,将所有的变量都存放在 主内存中,当线程使用变量时,会把主内存里面的变量 复制 到自己的工作空间或者叫作 私有内存 

avatar

刷新的场景:

  1. 主内存中有变量 x,初始值为 0
  2. 线程 A 要将 x 加 1,先将 x=0 拷贝到自己的私有内存中,然后更新 x 的值
  3. 线程 A 将更新后的 x 值回刷到主内存的时间是不固定的
  4. 刚好在线程 A 没有回刷 x 到主内存时,线程 B 同样从主内存中读取 x,此时为 0,和线程 A 一样的操作,最后期盼的 x=2 就会编程 x=1

原子性

原子性:原子(atom)指化学反应不可再分的基本微粒,原子性操作你应该能感受到其含义:

count++ 分解为四步,解释一下字节码的指令,

16 : 获取当前 count 值,并且放入栈顶
19 : 将常量 1 放入栈顶
20 : 将当前栈顶中两个值相加,并把结果放入栈顶
21 : 把栈顶的结果再赋值给 count

  • JDK 的 rt.jar 包中的 Unsafe 类提供了 硬件级别 的原子性操作

有序性

对于编译期可能对语句的执行进行了优化。

  • 如双重加锁检查的 instance = new Singleton()
    这 1 行代码转换成了 CPU 指令后又变成了 3 个,我们理解 new 对象应该是这样的:
1. 分配一块内存 M
2. 在内存 M 上初始化 Singleton 对象
3. 后 M 的地址赋值给 instance 变量但编译器擅自优化后可能就变成了这样:
1. 分配一块内存 M
2. 然后将 M 的地址赋值给 instance 变量
3. 在内存 M 上初始化 Singleton 对象

用户态与内核态

操作系统对程序的执行权限进行分级,分别为用户态和内核态。

  • 内核态: cpu可以访问计算机所有的软硬件资源
  • 用户态: cpu权限受限,只能访问到自己内存中的数据,无法访问其他资源

为什么要有用户态和内核态

系统需要限制不同的程序之间的访问能力,防止程序获取不相同程序的内存数据,或者外围设备的数据,并发送到网络,所有cpu划分出两个权限等级用户态和内核态

内核态:用户态如果要做一些比较危险的操作直接访问硬件,很容易把硬件搞死(格式化,访问网卡,访问内存)

用户态与内核态的性能开销

当发生用户态到内核态的切换时,会发生如下过程:

  1. 设置处理器至内核态。
  2. 保存当前寄存器(栈指针、程序计数器、通用寄存器)。
  3. 将栈指针设置指向内核栈地址。
  4. 将程序计数器设置为一个事先约定的地址上,该地址上存放的是系统调用处理程序的起始地址。
  5. 而之后从内核态返回用户态时,又会进行类似的工作。

用户态和内核态之间的切换有一定的开销,如果频繁发生切换势必会带来很大的开销,所以要想尽一切办法来减少切换

避免频繁切换

因为线程的切换会导致用户态和内核态之间的切换,所以减少线程切换也会减少用户态和内核态之间的切换。那么如何减少线程切换呢?

  • 无锁并发编程。多线程竞争锁时,加锁、释放锁会导致比较多的上下文切换
  • CAS算法。使用CAS避免加锁,避免阻塞线程
  • 使用最少的线程。避免创建不需要的线程协程。在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换

Java内存模型JMM

avatar

java内存模型是关注在虚拟机中把变量值存储到内存和从内存取出变量这样的底层细节。

此处的变量包括了实例字段、静态字段和构成数组对象的元素,但是不包括局部变量和方法参数。
如果局部变量是一个reference类型,引用的对象在java堆中,但是reference本身在java栈的局部变量表中是线程私有。

java内存模型规定了所有变量都存储在主内存,每条线程还有自己的工作内存,线程的工作内存保存了被该线程使用的变量的主内存副本。线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存的数据。不同线程的内存数据无法直接访问,均得通过主内存。

关于线程内存的复制,如果主内存有一个10MB的对象,线程会把对这个对象的引用、对象中在线程中的字段进行复制,但不会整个复制。

如果要把java的内存强行与Java内存区域做对应的话:

  • 主内存 -> java 堆
  • 工作内存 -> 虚拟机栈
  • 从更基础层次上,主内存直接对应物理硬件的内存。

volatile

性能:volatile变量的读操作性能与普通变量几乎没有差别,但是写操作可能会慢些,因为需要插入内存屏障指令来保证处理器不乱序执行。

当读一个 volatile 变量时, JMM 会把该线程对应的本地内存置为无效。线程接下来将从主内存中读取共享变量。
线程在【读取】共享变量时,会先清空本地内存变量值,再从主内存获取最新值

相关文章:

java并发

基本概念 并发编程可以抽象成三个核心问题: 分工、同步/协作、互斥分工 将当前 Sprint 的 Story 拆分成「合适」大小的 Task,并且安排给「合适」的 Team Member 去完成 拆分的粒度太粗,导致这个任务完成难度变高,耗时长,不易与其他人配合;拆分的粒度太细,又导致任务太多…...

Python Selenium Grid 环境快速搭建

今天在看selenium grid文档的时候,发现selenium grid4的设计还是不错的,想顺手体验一下,于是就发现了docker-selenium项目,可以快速的设置好selenium grid环境,非常简单方便。 然而后面准备用python去写个简单例子的时…...

电机控制系列模块解析(21)—— 弱磁控制

一、弱磁控制 常用的FW即弱磁控制方法一般为:电压外环控制、单个电流环控制、直接输出电压幅值分配控制、输出电压角度PI控制、不弱磁控制、直接解析解、查表、速度反比例曲线拟合等等。 弱磁控制相关因素:过调制(母线电压的剧烈波动&#x…...

【3dmax笔记】022:文件合并、导入、导出

文章目录 一、合并二、导入三、导出四、注意事项一、合并 只能合并 max 文件(高版本能够合并低版本模型,低版本不能合并高版本的模型)。点击【文件】→【导入】→【合并】: 选择要合并的文件,后缀名为3dmax默认的格式,max文件。 二、导入 点击【文件】→【导入】→【导…...

8、QT——QLabel使用小记2

前言:记录开发过程中QLabel的使用,持续更新ing... 开发平台:Win10 64位 开发环境:Qt Creator 13.0.0 构建环境:Qt 5.15.2 MSVC2019 64位 一、基本属性 技巧:对于Qlabel这类控件的属性有一些共同的特点&am…...

python实现读取串口数据-使用LibModbus库实现一个实时读取串口数据

在工业自动化领域,Modbus协议因其简单、可靠和广泛支持而备受青睐。其中,Modbus RTU(串行通信)以其低成本和易实施性在许多场景中发挥着重要作用。 01 Modbus RTU协议简介 Modbus RTU是一种基于串行通信的Modbus协议,…...

类与面向对象编程(Object-Oriented Programming, OOP)

类与面向对象编程(Object-Oriented Programming, OOP)(一) 对象比较:‘is’ 对比 ‘’ 当我还是个孩子的时候,我们的邻居拥有一对双胞胎猫咪。它们看起来几乎一模一样—同样的炭黑色毛发和同样锐利的绿色…...

引用数据类型 栈内存 堆内存

let m { a: 10, b: 20 }; let n m; n.a 15; console.log(m.a) // 15 原因:基本数据类型存储在栈内存中,引用数据类型存储在堆内存中 ,引用数据类型存储在堆内存中会在栈内存中创建一个指针,栈内存中的这个指针指向堆内存中的地…...

【class8】人工智能初步(图像识别-----卷积神经网络)

上节回顾 上节课,我们简单了解了图像识别和深度学习的相关知识。 快速回顾一下吧~ A图像识别是以图像的主要特征为基础的。B. 图像分辨率决定图像的质量。 C. 像素是图像中的最小单位D. 在图像识别的原理上,计算机和人类在本质…...

Node.js安装及环境配置(超详细!保姆级!!)

目录 一、进入官网地址下载安装包 二、安装程序 三、环境配置 四、测试 五、安装淘宝镜像 一、进入官网地址下载安装包 Node.js — Download Node.js (nodejs.org) 选择对应你系统的 node.js 版本,我选择的是Windows系统,64位 点击图中选项&#…...

利用反射如何动态生成sql

一.自定义注解 UpdateWhere Target({ElementType.FIELD}) //作用于类 Retention(RetentionPolicy.RUNTIME) //运行时有效 Documented //可以出现在文档里 Inherited public interface UpdateWhere {}二.创建实体类接受 pu…...

SpringBoot项目中使用Redis,Mybatis和JWT

在Spring Boot项目中,结合Redis,MyBatis和JWT的使用可以提供以下功能: Redis的作用: 1.缓存:Redis可以用作缓存存储,提高应用程序的性能和响应速度。特别是对于频繁读取但不经常更新的数据,如配…...

CSS2(一):CSS选择器

文章目录 1、CSS基础1.1 CSS简介1.2 CSS编写位置1.2.1 行内样式1.2.2 内部样式1.2.3 外部样式1.2.4 样式优先级 1.2.5 CSS代码风格 2、CSS选择器2.1、基本选择器2.1.1 通配选择器2.1.2 元素选择器2.1.3 类选择器2.1.4 ID选择器2.1.5 总结 2.2、CSS复合选择器2.2.1 交集选择器2.…...

LeetCode题练习与总结:不同的二叉搜索树--96

一、题目描述 给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。 示例 1: 输入:n 3 输出:5示例 2: 输入:n 1 输出&…...

第八十一章 将 Web 应用程序与远程 Web 服务器结合使用 - 如果从 Web 服务器提供静态文件

文章目录 第八十一章 将 Web 应用程序与远程 Web 服务器结合使用 - 如果从 Web 服务器提供静态文件如果从 Web 服务器提供静态文件配置 Web 服务器路径将虚拟目录添加到 IIS将别名添加到 Apache 配置 第八十一章 将 Web 应用程序与远程 Web 服务器结合使用 - 如果从 Web 服务器…...

AVL树、红黑树

数据结构、算法总述:数据结构/算法 C/C-CSDN博客 AVL树 定义 空二叉树是一个 AVL 树如果 T 是一棵 AVL 树,那么其左右子树也是 AVL 树,并且 ,h 是其左右子树的高度树高为 平衡因子:右子树高度 - 左子树高度 创建节点…...

Vscode编辑器 js 输入log自动补全

最近换了新电脑,新下载了Vscode,记录一下设置项。 Vscode 版本 想要的效果 js文件中输入log(点击tab键),自动补全为 console.log() Vscode 文件》首选项》设置 搜索:snippets Emmet: Show Suggestions…...

structured concurrency

1. 基于 c executions的异步实现 - 从理论到实践 - 知乎 (zhihu.com)...

【免费】在线识别通用验证码接口

模块优势价格5元1000次&#xff0c;每天免费100次api文档支持 使用量小的完全够用了 <?phpfunction Post_base64($base64_str){$url http://api.95man.com:8888/api/Http/Recog?Taken41******QK&imgtype1&len0 ; $fields array( ImgBase64>$base64_str); $ch…...

如何通过汽车制造供应商协同平台,提高供应链的效率与稳定性?

汽车制造供应商协同是指在汽车制造过程中&#xff0c;整车制造商与其零部件供应商之间建立的一种紧密合作的关系。这种协同关系旨在优化整个供应链的效率&#xff0c;降低成本&#xff0c;提高产品质量&#xff0c;加快创新速度&#xff0c;并最终提升整个汽车产业的竞争力。以…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

Ubuntu系统复制(U盘-电脑硬盘)

所需环境 电脑自带硬盘&#xff1a;1块 (1T) U盘1&#xff1a;Ubuntu系统引导盘&#xff08;用于“U盘2”复制到“电脑自带硬盘”&#xff09; U盘2&#xff1a;Ubuntu系统盘&#xff08;1T&#xff0c;用于被复制&#xff09; &#xff01;&#xff01;&#xff01;建议“电脑…...