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

并发编程小记1

什么时候用单线程什么时候用多线程图里展示了一个典型的网络请求场景左侧处理耗时1ms网络请求往返耗时25ms 25ms 50ms右侧处理耗时2ms整个流程总耗时1ms 25ms 2ms 25ms 53ms这里的瓶颈明显是网络 IO 等待50ms而不是 CPU 计算总共只占 3ms图里还提到了一个对比场景for() 1-1亿 --- 单线程这是纯 CPU 计算密集型任务什么时候用多线程对应图里的 IO 密集场景✅IO 密集型任务优先用多线程图里的文字也直接点明了io,访问网络,访问硬盘---IO密集--多线程合适适用场景网络请求API 调用、数据库查询、文件下载磁盘读写文件读写、数据库操作其他阻塞式等待如用户输入、队列等待为什么这类任务的大部分时间线程都在 “等待”等网络响应、等磁盘读写完成CPU 是空闲的。用多线程可以在等待的间隙让 CPU 去处理其他任务把等待时间 “利用起来”大幅提升整体效率。比如图里的场景如果同时发起多个请求就能重叠等待时间总耗时会从 53ms 降到接近 52ms1252效率翻倍。什么时候用单线程对应图里的 CPU 密集场景✅CPU 密集型任务优先用单线程或少量线程图里的for() 1-1亿就是典型例子纯计算、无等待全程都在占用 CPU。适用场景大规模数值计算、复杂算法运算视频 / 图片编码解码循环遍历、数据批量处理无 IO 操作为什么这类任务全程都在占用 CPU多线程会带来额外的线程切换开销反而降低效率多线程还会引发 CPU 缓存失效、资源竞争等问题进一步拖慢速度对于 Python 这类有 GIL全局解释器锁的语言多线程甚至无法真正并行执行 CPU 密集任务反而不如单线程高效一句话总结IO 密集型等待多、计算少用多线程让等待时间 “物尽其用”CPU 密集型计算多、等待少用单线程避免线程切换开销保证效率jion()函数的作用t1.join();作用让当前线程比如主线程等待t1线程执行完成再继续往下走。也就是说join()会阻塞当前线程直到t1线程死亡执行完毕后面的代码才会开始执行。1. 测量上下文切换的时长Lmbench3命令vmstat 1减少上下文切换1. 无锁并发编程原理多线程竞争锁时会触发阻塞 / 唤醒引发大量上下文切换。无锁编程通过避免锁竞争减少这类开销。实现思路数据分段按 ID 哈希取模让不同线程处理不同分段的数据从根源上避免共享资源竞争。典型场景分库分表、数据分片处理。2. CAS 算法原理Compare-And-Swap比较并交换是一种乐观锁机制通过硬件指令实现原子更新无需加锁。应用示例Java 中的java.util.concurrent.atomic包如AtomicInteger底层基于 CAS 实现线程安全避免了传统锁带来的阻塞和上下文切换。3. 使用最少线程原理线程过多会导致 CPU 调度频繁大量线程处于等待 / 就绪状态加剧上下文切换。优化方式线程数与 CPU 核心数匹配CPU 密集型任务核心数 1IO 密集型可适当增加但避免过度创建。避免 “任务少、线程多” 的场景减少不必要的线程创建。4. 使用协程原理协程是用户态的轻量级线程在单线程内实现多任务调度切换由用户程序控制无需内核参与。优势协程切换不涉及内核态 / 用户态切换开销极低大幅减少上下文切换次数。典型场景高并发 IO 场景如网络请求、异步处理通过协程实现高效的任务调度。目标通过减少大量处于WAITING状态的空闲线程降低系统上下文切换次数优化性能。减少上下文切换实战第一步获取线程快照jstack命令工具jstackJDK 自带的 Java 线程分析工具命令示例sudo -u admin /opt/ifeve/java/bin/jstack 31177 /home/tengfei.fangtf/dump17作用导出进程 ID 为31177的 Java 进程的所有线程快照保存为dump17文件。目的查看进程内所有线程的运行状态定位性能瓶颈。第二步统计线程状态分布命令示例grep java.lang.Thread.State dump17 | awk {print $2$3$4$5} | sort | uniq -c作用从线程快照中提取所有线程状态统计每种状态的线程数量。统计结果解读状态线程数含义RUNNABLE39线程正在运行或就绪等待 CPU 调度TIMED_WAITING(onobjectmonitor)21线程限时等待对象锁TIMED_WAITING(parking)6线程限时等待如 LockSupport.parkNanosTIMED_WAITING(sleeping)51线程限时休眠如 Thread.sleepWAITING(onobjectmonitor)305线程无限期等待对象锁Object.wait()WAITING(parking)3线程无限期等待如 LockSupport.park关键发现305 个线程处于WAITING(onobjectmonitor)状态占线程总数的绝大多数。第三步分析 WAITING 线程的具体行为查看线程栈信息打开dump文件一瞬间的信息查看处于WAITING(onobjectmonitor)状态的线程栈。关键栈信息示例http-0.0.0.0-7001-97 daemon prio10 tid0x000000004f6a8000 nid0x555e in Object.wait() [0x0000000052423000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method)根因定位这些线程是JBOSS 的工作线程都在执行Object.wait()方法处于等待状态。说明 JBOSS 线程池配置过大线程池里线程接收的任务太少大量线程都处于空闲等待状态。这些空闲线程会被操作系统频繁调度引发大量上下文切换消耗系统资源。第四步调整 JBOSS 线程池配置优化动作找到 JBOSS 的线程池配置文件将maxThreads最大工作线程数从250降低到100。关键配置示例解读maxThreads250 maxHttpHeaderSize8192 emptySessionPathfalse minSpareThreads40 maxSpareThreads75 maxPostSize512000 protocolHTTP/1.1 enableLookupsfalse redirectPort8443 acceptCount200 bufferSize16384 connectionTimeout15000 disableUploadTimeoutfalse useBodyEncodingForURItruemaxThreads线程池最大线程数原配置为 250优化后改为 100。minSpareThreads最小空闲线程数原配置为 40。maxSpareThreads最大空闲线程数原配置为 75。acceptCount等待队列长度原配置为 200。第五步验证优化效果操作步骤重启 JBOSS 服务使配置生效。再次使用jstack命令 dump 线程信息。统计处于WAITING(onobjectmonitor)状态的线程数量。优化结果WAITING状态的线程减少了 175 个。原理大量空闲线程减少后操作系统不需要频繁地在WAITING和RUNNABLE状态之间调度线程从而显著降低上下文切换次数。验证工具可使用vmstat命令观察cscontext switch列的数值变化确认上下文切换次数减少。死锁定义两个或多个线程互相持有对方需要的资源又都不肯释放自己已占有的资源导致所有线程永久阻塞、谁都无法继续执行程序卡死。二、死锁产生的四个必要条件必须同时满足才会死锁互斥条件资源同一时刻只能被一个线程占用别人不能抢。请求与保持条件线程已经持有至少一个资源又去请求新的资源不释放已占有的。不可剥夺条件资源只能由持有线程主动释放其他线程不能强行抢占。环路等待条件线程之间形成资源等待环路线程 A 等 B 的资源线程 B 等 A 的资源。只要破坏任意一个条件就能避免死锁。三、死锁产生常见场景多线程多把锁嵌套加锁顺序不一致线程互相持有对方需要的锁互相等待数据库多事务更新行加行锁顺序颠倒四、如何预防 / 避免死锁破坏四大条件统一加锁顺序所有线程按相同顺序获取多把锁从根源打破环路等待。主动释放资源申请新锁前先释放已持有锁破坏请求与保持。设置锁超时尝试加锁超时就放弃、回退不永久等待破坏不可剥夺。使用 tryLock 尝试获取锁拿不到锁就立刻放弃或重试不阻塞等待。减少嵌套锁尽量不写多重锁嵌套从业务上减少死锁概率。五、死锁如何排查jps查看 Java 进程 IDjstack 进程ID导出线程快照搜索Deadlock工具会自动检测并提示死锁线程查看线程栈看各自持有什么锁、等待什么锁定位代码位置Java并发机制的底层实现原理特性synchronizedvolatile主要作用保证原子性、可见性、有序性保证可见性、有序性不保证原子性适用场景多线程竞争下的复合操作如i状态标记、开关变量如boolean isRunning实现原理基于锁机制会阻塞其他线程基于内存屏障不会阻塞线程性能开销较高涉及锁竞争、线程上下文切换极低仅内存读写无阻塞是否能保证线程安全可以对代码块 / 方法加锁保证操作原子性仅在特定场景下无复合操作能保证✅synchronized读写都安全它能保证代码块 / 方法内的操作是原子性的同一时间只有一个线程能执行所以不管是读还是写操作都是线程安全的。⚠️volatile仅读安全写不安全尤其是复合写它只能保证变量的可见性和禁止指令重排序但不保证原子性单次读操作是安全的所有线程都能读到最新值。单次写操作如直接赋值flag true在特定场景下是安全的。复合写操作如count包含读 - 改 - 写三步完全不安全会出现线程安全问题关键概念可见性定义当一个线程修改了volatile修饰的共享变量其他线程能立刻读到最新值不会被 CPU 缓存或指令重排序延迟。底层原理写操作时强制将修改值刷回主内存读操作时强制从主内存读取最新值不使用 CPU 缓存避免了传统变量 “本地缓存副本” 导致的线程间数据不一致问题volatile的定义与实现原理一、volatile的定义背景Java 允许多线程访问共享变量为了保证变量更新的准确性和一致性通常需要通过排他锁如synchronized实现线程安全。volatile的定位Java 提供的一种更轻量、更便捷的同步机制在部分场景下可替代锁。核心语义如果一个字段被声明为volatileJava 线程内存模型会确保所有线程看到的这个变量的值是一致的即保证可见性。二、volatile的核心作用保证可见性多线程环境下当一个线程修改了volatile变量的值其他线程能立即感知到最新值不会因为 CPU 缓存或指令重排序导致 “读不到最新数据” 的问题。这也是它和普通变量最关键的区别之一。部分场景替代锁相比重量级锁如synchronizedvolatile使用更便捷、开销更低在无复合操作的场景下如状态标记可以替代锁实现线程安全。三、后续内容预告实现原理的底层支撑原文提到在深入讲解volatile的实现原理前会先介绍相关的 CPU 术语表 2-1这些术语是理解其底层实现的基础包括CPU 缓存L1/L2/L3 Cache缓存一致性协议如 MESI内存屏障Memory Barrier指令重排序等补充volatile的关键局限它不保证原子性对于count这类 “读 - 改 - 写” 复合操作volatile无法保证线程安全仍需使用锁或原子类如AtomicInteger。它不替代锁的全部功能仅适用于特定场景如状态标记、双重检查锁单例不能替代所有同步需求。术语英文核心作用 / 描述内存屏障memory barriers一组处理器指令限制内存操作的执行顺序是实现 volatile 有序性、可见性的核心底层指令。缓冲行缓存行cache lineCPU 缓存中可分配的最小存储单位处理器读写数据时会以整个缓存行为单位加载 / 写入数据。原子操作atomic operations不可被中断的单步或系列操作是实现无锁并发的基础。缓存行填充cache line fill处理器从内存读取数据时若数据可缓存会将整个缓存行加载到各级缓存L1/L2/L3。缓存命中cache hit后续访问的内存地址仍在缓存中处理器直接从缓存读取无需访问内存速度大幅提升。写命中write hit处理器写数据时目标地址已在缓存中直接写入缓存不写回内存。写缺失write misses the cache处理器写数据时目标地址不在缓存中需先加载缓存行再写入。1. 问题volatile 如何保证可见性图中明确指出要理解 volatile 的实现需要在X86 处理器下通过查看 JIT 编译器生成的汇编指令分析 volatile 变量写操作时 CPU 的行为。2. 核心底层机制补充完整volatile 的可见性和有序性本质上是通过内存屏障指令实现的写屏障Store Barrier在 volatile 变量写操作后插入强制将缓存中的修改刷回主内存并禁止后续指令重排序到写操作之前。读屏障Load Barrier在 volatile 变量读操作前插入强制从主内存读取最新值并禁止后续指令重排序到读操作之前。三、术语与 volatile 的关联内存屏障直接实现 volatile 的两大核心语义 —— 可见性强制刷写 / 读取主内存和有序性禁止指令重排序。缓存行 / 缓存一致性volatile 的写操作会触发缓存一致性协议如 MESI使其他 CPU 核心的缓存行失效被迫从主内存读取最新值从而保证可见性。原子操作volatile 不保证复合操作如count的原子性但单次读写操作本身是原子的依赖 CPU 的原子读写指令实现。volatile为什么不能保证准确性核心结论volatile 不保证原子性volatile只能保证可见性和禁止指令重排序但完全不保证复合操作的原子性。很多我们以为的 “简单操作”比如count在 CPU 层面其实是三步操作从主内存读取count的值到 CPU 缓存对值进行 1 计算将计算后的结果写回主内存而volatile只能保证第 1 步和第 3 步的 “可见性”但无法阻止多线程在第 1 步和第 3 步之间互相干扰导致数据丢失。

相关文章:

并发编程小记1

什么时候用单线程,什么时候用多线程?图里展示了一个典型的网络请求场景:左侧处理耗时:1ms网络请求往返耗时:25ms 25ms 50ms右侧处理耗时:2ms整个流程总耗时:1ms 25ms 2ms 25ms 53ms这里的…...

PCIe调试避坑指南:当你的设备报Malformed TLP/UR/UC错误时,到底发生了什么?

PCIe调试实战:Malformed TLP/UR/UC错误排查全解析 当PCIe设备突然抛出Malformed TLP、UR(Unsupported Request)或UC(Unexpected Completion)错误时,很多工程师的第一反应往往是翻查协议手册。但真实调试场景…...

从信息网络到能源网络:聊聊2012年那篇关于‘能源路由器’的论文,它今天还有哪些启发?

能源路由器的十年回望:从TCP/IP隐喻到虚拟电厂的现实启示 十二年前那篇将能源网络类比TCP/IP协议的论文,在今天看来更像是一封来自过去的预言书。当我们在2023年讨论虚拟电厂和分布式能源交易时,会发现那些曾被视作天马行空的构想——能源操作…...

m4s-converter:一键解决B站缓存视频的格式兼容难题

m4s-converter:一键解决B站缓存视频的格式兼容难题 【免费下载链接】m4s-converter 一个跨平台小工具,将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 你是否曾经遇到过这样的场景&…...

用LoRA微调LLaMA2时,你的显存和参数到底省在哪了?一个公式讲明白

LoRA微调LLaMA2的显存优化原理与工程实践指南 当开发者尝试在消费级显卡上微调大语言模型时,显存限制往往成为首要障碍。以LLaMA2-7B为例,全量微调需要约120GB显存,远超RTX 3090等主流显卡的24GB容量。低秩适配(LoRA)技…...

ArcGIS老用户看过来:手把手教你为ArcMap 10.x定制专属Word报告插件(基于AddIN开发)

ArcGIS老用户进阶指南:打造智能Word报告生成插件 在GIS行业深耕多年的专业人士都清楚,ArcMap 10.x系列依然是许多企业和机构的核心生产力工具。尽管Esri已经将重心转向ArcGIS Pro,但大量历史项目、定制化工作流和团队使用习惯使得ArcMap仍然活…...

Windows电脑直接运行安卓应用:APK安装器完全指南

Windows电脑直接运行安卓应用:APK安装器完全指南 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 你是否曾幻想过在Windows电脑上流畅运行安卓应用&#xff…...

暖风机如何实现稳定高效的采暖输出?

一、核心结论NT‑5TS型暖风机可依托标准化结构与性能参数,满足常规工业空间采暖供热需求,整体运行能耗合理、散热效率稳定,适配多场景采暖工况。该设备经暖通设备性能检测标准核验,在额定工况下各项指标均达到行业通用使用要求&am…...

H5GG完整指南:如何用JavaScript和HTML5轻松修改iOS游戏内存

H5GG完整指南:如何用JavaScript和HTML5轻松修改iOS游戏内存 【免费下载链接】H5GG an iOS Mod Engine with JavaScript APIs & Html5 UI 项目地址: https://gitcode.com/gh_mirrors/h5/H5GG 你是否曾经想过修改iOS游戏中的数值,却因为复杂的越…...

H5GG iOS模组引擎:基于JavaScript的iOS应用内存操作与界面定制技术实现

H5GG iOS模组引擎:基于JavaScript的iOS应用内存操作与界面定制技术实现 【免费下载链接】H5GG an iOS Mod Engine with JavaScript APIs & Html5 UI 项目地址: https://gitcode.com/gh_mirrors/h5/H5GG H5GG是一款创新的iOS模组引擎,通过Java…...

163MusicLyrics:一站式音乐歌词获取与处理工具完全指南

163MusicLyrics:一站式音乐歌词获取与处理工具完全指南 【免费下载链接】163MusicLyrics 云音乐歌词获取处理工具【网易云、QQ音乐】 项目地址: https://gitcode.com/GitHub_Trending/16/163MusicLyrics 在音乐欣赏和内容创作中,精准的歌词同步是…...

深度学习CNN(一)—— 卷积运算的本质(三十八)

1. 定位导航 🎉 第 9 章 CNN 大门正式开启! CNN 是深度学习历史上最具影响力的架构创新之一: 2012 AlexNet:ImageNet 革命,开启深度学习时代 2015 ResNet:突破"深度极限" 2020 Vision Transformer:CNN 的最大竞争对手出现 直到 2024 年:CNN 仍是图像处理、…...

深度扒一扒GEO(生成式引擎优化)的底层技术架构

Gartner预测2026年传统搜索流量将下降25%,而国内生成式AI用户已破5亿。 当你的潜在客户都在问豆包、Kimi或DeepSeek“哪个牌子好”时,你的官网排名第一还有用吗?没用。因为AI直接给了答案,用户根本没点进来。 这就是GEO&#xff…...

为初创团队构建AI应用时如何利用Taotoken控制初期成本

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 为初创团队构建AI应用时如何利用Taotoken控制初期成本 对于资源有限的初创团队而言,在开发AI功能原型时,最…...

CSL编辑器技术深度解析:基于HTML5的学术引用样式编辑全栈指南

CSL编辑器技术深度解析:基于HTML5的学术引用样式编辑全栈指南 【免费下载链接】csl-editor cslEditorLib - A HTML 5 library for searching and editing CSL styles 项目地址: https://gitcode.com/gh_mirrors/csl/csl-editor CSL编辑器是一个基于HTML5技术…...

高效掌握Simscape Electrical:BLDC电机控制器设计的5大关键技术实战

高效掌握Simscape Electrical:BLDC电机控制器设计的5大关键技术实战 【免费下载链接】Design-motor-controllers-with-Simscape-Electrical This repository contains MATLAB and Simulink files used in the "How to design motor controllers using Simscape…...

3个超实用场景解析:Cloud Document Converter如何让飞书文档转换变得轻松

3个超实用场景解析:Cloud Document Converter如何让飞书文档转换变得轻松 【免费下载链接】cloud-document-converter Convert Lark Doc to Markdown 项目地址: https://gitcode.com/gh_mirrors/cl/cloud-document-converter 还在为飞书文档的格式转换问题而…...

解决企业IT服务管理复杂性的iTop开源CMDB架构实践

解决企业IT服务管理复杂性的iTop开源CMDB架构实践 【免费下载链接】iTop A simple, web based CMDB & IT Service Management tool 项目地址: https://gitcode.com/gh_mirrors/it/iTop 在数字化转型时代,企业面临IT配置信息分散、工单流转低效、资产跟踪…...

别再踩坑了!Vue2项目里用Swiper5.4.5做轮播,这几个配置项(observer/observeParents)不加真不行

Vue2项目中Swiper5.4.5轮播图动态适配避坑指南 轮播图作为现代Web应用中最常见的交互组件之一,几乎成为每个前端项目的标配。在Vue2生态中,Swiper凭借其丰富的功能和灵活的配置,成为开发者实现轮播效果的首选库。然而,许多初中级开…...

深耕 AI 全域布局,探词科技凭硬核实力领跑 GEO 新赛道

在人工智能全面渗透各行各业的当下,传统线上流量玩法逐渐触顶,依托大模型生态搭建品牌长效传播阵地,已然成为企业数字化转型的核心突破口。作为国内专注 AI 品牌全域布局的专业服务商,探词科技深耕 GEO 智能优化领域,凭…...

别再手动算矩阵了!COMSOL中矢量与矩阵变换的保姆级配置指南(附避坑点)

COMSOL中矢量与矩阵变换的高效配置与实战避坑指南 在COMSOL Multiphysics的建模过程中,矢量与矩阵操作是处理复杂物理场问题的核心技能之一。许多工程师和研究人员在初次接触COMSOL的变量定义系统时,往往会陷入一个误区——试图像常规编程语言那样直接定…...

你的STM32调试信息用对了吗?深入对比.axf文件与addr2line.exe的配合之道

STM32调试进阶:解密.axf文件与addr2line的黄金组合 调试嵌入式系统时,最令人沮丧的莫过于设备突然崩溃,而你却对问题源头一无所知。作为一名长期与STM32打交道的开发者,我经历过无数次这样的时刻,直到真正理解了调试信…...

AI大模型时代:小白程序员必备!抓住机遇,收藏这份企业发展指南

AI大模型正深刻改变企业与市场格局。本文探讨了AI大模型对企业效率、决策、商业模式及竞争力的提升作用,并揭示了市场、技术、人才与合作四大机遇。企业需加强技术研发、培养人才、优化流程、创新模式,并注重数据安全与行业合作。紧跟AI大模型浪潮&#…...

ME_PURCHDOC_POSTED

创建采购订单时常用的保存增强ME_PROCESS_PO_CUST~POST里是没有订单号的可以使用ME_PURCHDOC_POSTED来做相关处理...

无王无帝定乾坤,来自田间第一人 海棠藏圣定山河

无王无帝定乾坤,来自田间第一人。 自古山河安定,世人皆归功于帝王镇守、朝堂统御, 仿佛万里乾坤唯有王权可镇、唯有霸业可安。 然则山河气运自有天道,世间安定自有公理, 强权只能维系一时疆域,正道方能稳固…...

无王无帝定乾坤,来自田间第一人 凰标传世照千秋

无王无帝定乾坤 ——来自田间第一人华夏文明千年流转,王朝霸业此起彼伏。 无数帝王功业随岁月风化,无数朝堂规制随朝代更迭消散。 真正能够跨越岁月、贯穿古今、安定世道、照亮千秋的, 从不是一时的权位霸业,而是亘古不变的公道正…...

无王无帝定乾坤,来自田间第一人 大道同行赴新程

无王无帝定乾坤,来自田间第一人。 ——题记一、旧世终章:王权尽头的暮色朝代崛起方式落幕原因秦铁血征伐暴政失心汉布衣起义外戚乱政唐门阀更迭藩镇割据……………… “千秋岁月流转,世道几经更迭,无数王朝踏着烽烟崛起&#xff0…...

无王无帝定乾坤,来自田间第一人 海棠山铁哥立标兴文脉

无王无帝定乾坤 ——来自田间第一人 一、破题:王权文脉之弊 旧序新局依附王权扎根民间权贵定义苍生共塑礼制浮华守心向善阶级垄断平等普惠文脉若随王朝而兴,必随王朝而竭; 唯有根植人心,方可生生不息。 二、田间崛起:…...

无王无帝定乾坤,来自田间第一人 凰标为律正人心

无王无帝定乾坤,来自田间第一人。 世间最大的乱象,从来不止山河动荡、世道纷争,更是人心失序、良知蒙尘。一、旧世千年:王权为纲,律法为束旧制之弊具体表现规则来源由权贵制定,标准随权势偏移治理逻辑重压制…...

如何在Inkscape中快速实现专业级光线追踪?终极免费光学设计指南

如何在Inkscape中快速实现专业级光线追踪?终极免费光学设计指南 【免费下载链接】inkscape-raytracing An extension for Inkscape that makes it easier to draw optical diagrams. 项目地址: https://gitcode.com/gh_mirrors/in/inkscape-raytracing Inks…...