程序员的护城河-并发编程
- 👏作者简介:大家好,我是爱吃芝士的土豆倪,24届校招生Java选手,很高兴认识大家
- 📕系列专栏:Spring源码、JUC源码
- 🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦
- 🍂博主正在努力完成2023计划中:源码溯源,一探究竟
- 📝联系方式:nhs19990716,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬👀
文章目录
- 前言
- 并发编程详解
- 感慨
- 进程与线程
- 线程
- 线程常用方法及状态
- 共享资源和线程安全性
- synchronized底层原理
- wait notify
- 线程状态与ReentrantLock
- Java内存模型
- Java无锁模型
- 并发编程大师的原子累加器底层优化原理(与人类的优秀灵魂对话)
- 不可变设计
- 手写简易版线程池思路
- 线程池
- ReentrantLock原理
- 读写锁
- ThreadLocal
- CompletableFuture
- 同步协作
- 线程安全集合
- 并发编程实践
- 总结
前言
世间不如意十之八九。如果没办法一次到位,就分阶段实现吧。
并发编程详解
感慨
历时一个月,从一个只知道背八股的选手,到了对JAVA中常见的并发编程知识熟悉,这是一个蜕变,其实并发编程并不是一个单单的部分,当完整的学习完一个体系,就会发现,很多框架、中间件等都有并发编程的思想,比如Redis等,学会并发编程后也代表着真正的打开了走向高阶程序员的大门,这个过程注定是艰辛的,但是收获确实巨大的!!!
为此,奔着笔记和分享的原则,将整个学习体系的思考和研读整理成博客,供他人参考和指正,在此也希望能获得大家宝贵的意见,一起学习,共同进步。
进程与线程
概述进程与线程之间的关系以及简单测试多线程的好处
👉👉👉 剑指JUC原理-1.进程与线程-CSDN博客
线程
主要概述创建线程的方式以及线程运行的原理
👉👉👉 剑指JUC原理-2.线程-CSDN博客
线程常用方法及状态
本章节主要概述了JUC常见的API 以及 几种线程状态 和 其资源占用情况
👉👉👉 剑指JUC原理-3.线程常用方法及状态-CSDN博客
共享资源和线程安全性
本章节详细的介绍了线程安全性,列举多个案例来论述 共享资源读写问题、是否安全
👉👉👉 剑指JUC原理-4.共享资源和线程安全性-CSDN博客
synchronized底层原理
本章节尽可能的去讲解了synchronized 的发展流程,包括Monitor、重量级锁、轻量级锁、偏向锁、自旋优化等等。
👉👉👉 剑指JUC原理-5.synchronized底层原理-CSDN博客
wait notify
本章节主要讲解的是 关于 同步实现 和 异步实现的原理,同步实现通过观察join源码发现其实是一种保护性暂停的策略,而异步实现其实有点像消息队列的感觉,本质上就是 不管生产者传过来过,消费者不会立马消费掉,这里其实使用阻塞队列的思想就可以实现。
👉👉👉 剑指JUC原理-6.wait notify-CSDN博客
线程状态与ReentrantLock
本章节其实主要介绍了 死锁问题的发生以及如何的排查死锁,具体的可以使用jsp + jstack && top + top H + jstack && jconsloe 来排查问题,同时介绍了与synchronized 对比的一种可重入锁 ReentrantLock 的特点。
👉👉👉 剑指JUC原理-7.线程状态与ReentrantLock-CSDN博客
Java内存模型
本章节主要介绍了 Java内存模型 中的 原子性 可见性 有序性的观点,并着重的介绍了如 volatile 内存屏障的相关原理,并且以 高并发下的单例模式举例来论证 三大特性。
👉👉👉 剑指JUC原理-8.Java内存模型-CSDN博客
Java无锁模型
本章节主要介绍了 无锁模型cas具体是什么原理,以及基于cas的原子类,最终剖析了其最底层unsafe的实现,其底层是通过获取偏移量然后再进行比较。
👉👉👉 剑指JUC原理-9.Java无锁模型-CSDN博客
并发编程大师的原子累加器底层优化原理(与人类的优秀灵魂对话)
本章节主要介绍了 原子累加器 LongAdder的底层实现,其性能较好,本质上适合高并发场景的累加,分为有竞争 和 无竞争,有竞争做的优化是 创建一个累加单元数组,并发的去累加,并且针对各种逻辑进行了详细的校验。
但是有利也有弊,其性能非常好,适合高并发场景,但是精准度存在一定的问题
在这里只着重介绍一下 longadder 的 sum操作。
当我们最终获取计数器值时,我们可以使用LongAdder.longValue()
方法,其内部就是使用sum
方法来汇总数据的。
java.util.concurrent.atomic.LongAdder.sum()
:
public long sum() {Cell[] as = cells; Cell a;long sum = base;if (as != null) {for (int i = 0; i < as.length; ++i) {if ((a = as[i]) != null)sum += a.value;}}return sum;
}
实现很简单,遍历cells
数组中的值,然后累加.
看上去LongAdder
的性能全面超越了AtomicLong
,而且阿里巴巴开发手册也提及到 推荐使用 LongAdder 对象,比 AtomicLong 性能更好(减少乐观 锁的重试次数),但是我们真的就可以舍弃掉LongAdder
了吗?
当然不是,我们需要看场景来使用,如果是并发不太高的系统,使用AtomicLong可能会更好一些,而且内存需求也会小一些。
我们看过sum()方法后可以知道LongAdder在统计的时候如果有并发更新,可能导致统计的数据有误差。
而在高并发统计计数的场景下,才更适合使用LongAdder。
总结
LongAdder中最核心的思想就是利用空间来换时间,将热点value分散成一个Cell列表来承接并发的CAS,以此来提升性能。
LongAdder的原理及实现都很简单,但其设计的思想值得我们品味和学习。
👉👉👉 剑指JUC原理-10.并发编程大师的原子累加器底层优化原理(与人类的优秀灵魂对话)-CSDN博客
不可变设计
本章节主要介绍了 之所以会出现线程安全问题的原因,并结合String 中不可变设计 final 引出享元模式
👉👉👉 剑指JUC原理-11.不可变设计-CSDN博客
手写简易版线程池思路
本章节主要介绍了 一个简易版本线程池的设计思路,其本质其实就是阻塞队列,并且讲 核心线程的run方法重写,使其能够不停地复用,并且在复用的过程中还可以选择那种复用策略,是死等还是超时等待,最后再设计拒绝策略即可。
👉👉👉 剑指JUC原理-12.手写简易版线程池思路-CSDN博客
线程池
本章节主要介绍了真正的线程池,讲解了其几个核心参数 以及 FutureTask实现 和 Tomcat对线程池改造的思路。
👉👉👉 剑指JUC原理-13.线程池-CSDN博客
ReentrantLock原理
本章节首先介绍了AQS指导思想,然后又深入ReentrantLock源码去探究 公平非公平、可重入、可打断、await、signal等原理。
👉👉👉 剑指JUC原理-14.ReentrantLock原理-CSDN博客
读写锁
本章节介绍了基于ReentrantLock得读写锁,其实本质上换汤不换药,虽然分为了读写,但是只需要合理的控制state的高16位 和 低16位即可,同时在等待队列中做好新的标记,新增了shared 和 Ex标记,如果读获取到锁,还需要看看后面还有没有对应shared状态的一并解锁。
👉👉👉 剑指JUC原理-16.读写锁-CSDN博客
ThreadLocal
本章节首先介绍了ThreadLocal的基本使用场景,其次深入对应常用方法的源码,最后 针对可能存在内存泄漏的情况 以及 出现hash冲突时是怎么实现的(使用了线性探测法)
👉👉👉 剑指JUC原理-15.ThreadLocal-CSDN博客
CompletableFuture
本章节主要介绍了Future的加强版 CompletableFuture 的使用,其中调用链逻辑有 后一步需要前一步、需要不需要返回值、将所有的结果整合起来等,合理的使用能够极大的提高使用效率,但是 如果使用的话,最好在get处设置超时时间,并配置 complete 返回默认值。
👉👉👉 剑指JUC原理-17.CompletableFuture-CSDN博客
同步协作
本章节主要介绍了信号量同步方面原理,其实还是基于ReentrantLock的思路进行设计,所以可见AQS思想有多么的重要了,其次还介绍了 线程协调。
👉👉👉 剑指JUC原理-18.同步协作-CSDN博客
线程安全集合
本章节主要介绍了常见的第三代线程安全集合,当然得需要先学会其前置知识HashMap,详细介绍了HashMap在多线程的情况下出现的问题,以及ConcurrentHashMap 在不同的版本做的改进,然后还有阻塞队列 以及 CopyOnWrite思想,当然最本质的还是 一致性 和 并发性的问题,这个最直接的体现就是数据库的MVCC 和 LongAddar。
👉👉👉 如果面试也能这样说HashMap,那么就不会有那么多遗憾!-CSDN博客
👉👉👉 剑指JUC原理-19.线程安全集合-CSDN博客
并发编程实践
相信通过前面铺垫的20章,对于并发编程在原理层次应该是非常熟悉的了,在我的认知里,如果学习了原理性的知识而不去实战,那么这样学习是完全没有意义的,所以为了巩固我之所学,一个集成了网络上众多并发实战应用性的专题应运而生,详细的介绍了并发编程到底可以做什么,到底能够解决那些实际的问题,以及其局限性的思考,这些在我眼里是非常重要的,也就是知行合一的过程!
👉👉👉 剑指JUC原理-20.并发编程实践-CSDN博客
总结
学习JUC是完善整个后端体系必不可少的一环,因为很多Java后端的中间件或者框架其本身内部大量的涉及到了JUC的部分,并且也可以在阅读JUC源码的过程中明白思想,其实思想都是互通的,例如ReentrantLock的原理本质上和Redisson 的原理是类似的,那么就可以迅速过度到分布式锁的使用中。
总的来说,当完整的学习完JUC的部分,也相当于内功更胜一步,这比我当初做完谷粒商城的感觉还好,感觉作为程序员的核心素养更强了,感触良多,耗时一个月,其所体现的绝不是这二十一篇文章这么简单,更多的是传递思想,传递动力,我行你也行的态度!!!
最后分享给大家一句我非常喜欢的话吧。
种一棵树最好的时间是十年前,其次是现在
相关文章:
程序员的护城河-并发编程
👏作者简介:大家好,我是爱吃芝士的土豆倪,24届校招生Java选手,很高兴认识大家📕系列专栏:Spring源码、JUC源码🔥如果感觉博主的文章还不错的话,请👍三连支持&…...

外卖小程序系统:数字化餐饮的编码之道
在当今数字化时代,外卖小程序系统成为了餐饮业的一项技术巨制。这个系统不仅提供了便捷的点餐体验,更通过先进的技术手段,实现了高效订单处理、实时配送追踪以及个性化推荐。让我们深入了解外卖小程序系统的技术魔法,一起揭秘数字…...

单链表相关面试题--1.删除链表中等于给定值 val 的所有节点
/* 解题思路:从头节点开始进行元素删除,每删除一个元素,需要重新链接节点 */ struct ListNode* removeElements(struct ListNode* head, int val) {if(head NULL)return NULL;struct ListNode* cur head;struct ListNode* prev NULL;while…...
一生一芯18——Chisel模板与Chisel工程构建
Chisel模板链接如下: 链接: https://pan.baidu.com/s/1DNDKpz5VnTxPgoZBBOd-Ww?pwdrevg 提取码: revg Chisel转Verilog模板如下: 链接: https://pan.baidu.com/s/1T9JQL5BccxqI4bscfU-JyA?pwd7rw2 提取码: 7rw2 以下使用sbt作为构建工具 Chisel项目构…...
ES6 class类
基本介绍 1. constructor constructor()方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。 一个类必须有constructor()方法,如果没有显式定义,一个空的constructor()方法会被默认添加。如: class Po…...

Java的IO流-打印流
打印流 PrintStream public void println()自动换行 PrintWriter package com.itheima.println;import java.io.FileInputStream; import java.io.PrintStream; import java.io.PrintWriter;public class Test2 {public static void main(String[] arg…...

如何使用$APPEALS法,分析用户期待?
$APPEALS分析法是一种用于分析用户期待和需求的方法,它可以帮助企业全方位多角度地了解客户对产品的期望,有助于企业多维度有侧重地调整市场规划和产品改进策略,帮助企业打造优势产品,提高市场竞争力。 下面是使用$APPEALS分析法来…...

南京工程学院数据结构考试纲要
...
C++中将 sizeof() 用于类
C中将 sizeof() 用于类 您知道,通过使用关键字 class 声明自定义类型,可封装数据属性和使用数据的方法。运算符 sizeof( )用于确定指定类型需要多少内存,单位为字节。这个运算符也可用于类,在这种情况下,它将指出类声…...
Android studio访问选程https接口(.crt handshake)
如果服务器是https的,访问受限怎么办?有两种方法,一种是接受一切证书个人官方正式非正式,当然这样就牺牲了安全性,网上方法很多,我现在教大家如何去验证crt文件 首先服务器是https的,必然有几个…...
设计模式(一)-设计原则(1)
六大设计原则 1、单一职责原则 特点: 类和方法属性等,都应当遵守单一职责。尽可能保持统一性,单一性。 含义: (1)统一性,定义一个模块就必须要符合所有对象的行为特征。比如声明一个 Animal 类…...

Linux|僵死进程
1.僵死进程产生的原因或者条件: 什么是僵死进程? 当子进程先于父进程结束,父进程没有获取子进程的退出码,此时子进程变成僵死进程. 简而言之,就是子进程先结束,并且父进程没有获取它的退出码; 那么僵死进程产生的原因或者条件就是:子进程先于父进程结束,并且父进程没有获取…...

JDY蓝牙注意事项
波特率设置:9600,不接受115200,或者38400. 不同于WiFi测试,jdy蓝牙不接受AT"指令,可以使用“ATVERSION"指令测试 安信可公司的那个蓝牙指令在这里没有用,不知道是不是生产的公司不一样...

服务器IPMI管理操作
简介:智能平台管理界面(IPMI,Intelligent Platform Management Interface)是管理基于 Intel 结构的企业系统中所使用的外围设备采用的一种工业标准,用户可以利用IPMI监视服务器的物理健康特征,如温度、电压、风扇工作状…...

自动驾驶学习笔记(九)——车辆控制
#Apollo开发者# 学习课程的传送门如下,当您也准备学习自动驾驶时,可以和我一同前往: 《自动驾驶新人之旅》免费课程—> 传送门 《Apollo Beta宣讲和线下沙龙》免费报名—>传送门 文章目录 前言 控制器设计 比例积分微分控制 线性…...

HTML5学习系列之项目实战1
HTML5学习系列之项目实战1 前言代码记录问题总结 前言 学习记录 代码 <div id"player"><audio id"musicbox"></audio><div id"controls" class"clearfix controls"><div id"play" class"…...

git 提交成了LFS格式,如何恢复
平常习惯使用sourceTree提交代码,某次打开时弹出了一个【是否要使用LFS提交】的确认弹窗,当时不知道LFS是什么就点了确认,后续提交时代码全变成了这个样子 因为是初始化的项目首次提交,将近四百个文件全被格式化成了这个样子&…...
【ISP图像处理】Demosaic去马赛克概念介绍以及相关方法整理
1. 基本定义 使用彩色滤光器阵列(CFA)的数码相机需要一个去马赛克程序来形成完整的RGB图像。一般的相机传感器都是采用彩色滤光片阵列(CFA)放置在光感测单元上,在每个像素处仅捕获三种原色成分中的一种。 去马赛克方法主要关注于复原非常规区域,比如边缘…...

单图像3D重建AI算法综述【2023】
计算机视觉是人工智能的一个快速发展的领域,特别是在 3D 领域。 本概述将考虑一个应用任务:2D 和 3D 环境之间的转换。 在线工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编…...
three.js相机调用reset方法复原但无法完全复原
目录 一、问题 二、原因 三、总结 一、问题 需求:经过多次旋转、平移等变换后,希望恢复到初次渲染的角度、位置。结果发现: three.js oribtControls调用 一次reset方法 无法完全复原;需要多次调用后才能复原。 this.orbitControls.reset…...

大话软工笔记—架构模型
1. 架构模型1—拓扑图 (1)拓扑图概念 拓扑图,将多个软件系统用网络图连接起来的表达方式。 (2)拓扑图分类 总线型结构 比较普遍采用的方式,将所有的系统接到一条总线上。 星状结构 各个系统通过点到…...

关于智能体API参考接口
关于智能体在Flask的源码:请求体(在payload里的是请求体)、请求头(在headers里的i局势请求头)。 我的例子: 我的疑问:为什么没按Coze官方API文档格式,在Apifox里发POST请求却能收到回复? 1. 你…...
使用 C/C++ 和 OpenCV 添加图片水印
使用 C/C 和 OpenCV 添加图片水印 🖼️ 在数字图像处理中,添加水印是一种常见的操作,可以用于版权保护、品牌宣传或信息标注。本文将介绍如何使用 C/C 和强大的计算机视觉库 OpenCV 来实现将自定义水印(图片或文字)添…...

springcloud SpringAmqp消息队列 简单使用
这期只是针对springBoot/Cloud 在使用SpringAmqp消息队列的时候遇到的坑。 前提 如果没有安装RabbitMQ是无法连接成功的!所以前提是你要安装好RabbitMQ。 docker 安装命令 # 拉取docker镜像 docker pull rabbitmq:management# 创建容器 docker run -id --namera…...
CppCon 2015 学习:Memory and C++ debugging at Electronic Arts
这是关于 C 游戏开发中内存接口与调试工具演进 的介绍,主要回顾了从早期到现在平台上的内存与调试策略变化: 游戏平台演进与内存接口编程风格 2000年 (PlayStation 2) 编程风格偏向嵌入式 C 风格。系统资源有限(例如 32MB RAM)…...

Python 中 Django 中间件:原理、方法与实战应用
在 Python 的 Web 开发领域,Django 框架凭借其高效、便捷和功能丰富的特点备受开发者青睐。而 Django 中间件作为 Django 框架的重要组成部分,犹如 Web 应用的 “交通枢纽”,能够在请求与响应的处理流程中,实现对请求和响应的拦截…...

stm32-c8t6实现语音识别(LD3320)
目录 LD3320介绍: 功能引脚 主要特色功能 通信协议 端口信息 开发流程 stm32c8t6代码 LD3320驱动代码: LD3320介绍: 内置单声道mono 16-bit A/D 模数转换内置双声道stereo 16-bit D/A 数模转换内置 20mW 双声道耳机放大器输出内置 5…...

Docker构建Vite项目内存溢出:从Heap Limit报错到完美解决的剖析
问题现象:诡异的"消失的index.html" 最近在CI/CD流水线中遇到诡异现象:使用Docker构建Vite项目时,dist目录中缺少关键的index.html文件,但本地构建完全正常。报错截图显示关键信息: FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out…...
QGraphicsView中鼠标点击与移动事件传递给MainWindow
在Qt图形应用程序开发中,QGraphicsView和QGraphicsScene框架提供了强大的2D图形显示功能。然而,当我们需要在主窗口(MainWindow)中处理这些视图中的鼠标事件。 问题背景 在典型的Qt图形应用程序架构中: MainWindow └── QGraphicsView└── QGraphicsScene└── QGra…...

前后端分离开发 和 前端工程化
来源:黑马程序员JavaWeb开发教程,实现javaweb企业开发全流程(涵盖SpringMyBatisSpringMVCSpringBoot等)_哔哩哔哩_bilibili 前后端混合开发: 需要使用前端的技术栈开发前端的功能,又需要使用Java的技术栈…...