Java高并发理论基础
并发级别
由于临界区的存在,多线程之间的并发必须受到控制。根据控制并发的策略,我们可以把并发的级别分为 阻塞、无饥饿、无障碍、无锁、无等待
几种。
阻塞
一个线程是阻塞的,那么在其他线程释放资源之前,当前线程无法继续执行。当我们使用sychronized关键字或者重入锁时,我们得到的就是阻塞的线程。
sychronized关键字和重入锁(ReentrantLock)都试图在执行后续代码之前,得到临界区的锁,如果得不到,线程就会被挂起等待,直到占有了所需资源为止。
无饥饿
如果线程之间是有优先级的,那么线程调度的时候总是倾向于满足高优先级的线程。即,对于同一个资源的分配,是不公平的。
对于非公平锁,系统允许高优先级的线程插队,这样有可能导致低优先级线程产生饥饿。
如果锁是公平的,按照先来后到的原则,那么饥饿就不会产生。所有线程都有机会执行。
无障碍
无障碍是一种最弱的非阻塞调度(乐观锁)。两个线程无障碍的执行,那么不会因为临界区的问题导致一方被挂起,对于无障碍的线程来说,双方共同修改临界区的资源,如果一方把资源修改坏,会立即对自己所做的修改进行回滚,确保数据安全。
阻塞的控制方式属于悲观策略,无障碍(非阻塞)的调度就是一种乐观策略。
一种可行的无障碍实现可以依赖一个“一致性标记”(版本号或者CAS机制都依赖于这种实现),线程在操作之前,先读取并保存这个标记,在操作完成后,再次读取,检查这个标记是否被更改过,如果两者一致,则说明资源访问没有冲突。如果不一致,则重试操作。
无锁
无锁的并行都是无障碍的。在无锁的情况下,所有的线程都能尝试对临界区进行访问,但不同的是,无锁的并发保证必然有一个线程能够在有限步内完成操作离开临界区。
在无锁的调用中,一个典型的特点是可能会 包含一个无穷循环。在这个循环中,线程会不断尝试修改共享变量。如果没有冲突,修改成功,程序退出,否则继续尝试修改。
但无论如何,无锁的并行总能保证有一个线程是可以胜出的。
如下:
无等待
无锁只要求有一个线程可以在有限步骤内完成操作,而无等待要求所有线程必须在有限步骤内完成。这样就不会引起饥饿问题。如果限制这个步骤的上限,还可以进一步分解为有界无等待和线程数无关的无等待几种。
一种典型的无等待结构是RCU(Read Copy Update).他的基本思想是,对数据的读不加控制,在写数据的时候,先取得原始数据的副本,接着只修改副本数据,修改完成后,在合适的时机写回数据。(COW 写时复制)
Java内存模型(JMM)
JMM的关键技术点都是围绕着多线程的原子性、可见性和有序性来建立的。
原子性
原子性指一个操作是不可中断的。即使在多个线程在一起执行的时候,一个操作一旦开始就不会被其他线程干扰。
可见性
可见性是指当一个线程修改了某一个共享变量的时候,其他线程是否能够立即知道这个修改。
在CPU1和CPU2上各运行一个线程,他们共享变量t,由于编译器优化或者硬件优化的缘故,在CPU1上的线程将变量t缓存到cache或者寄存器中,在这种情况下,CPU2上的线程对共享变量做了修改,CPU1上的线程无法意识到这种改动,依然会读取缓存值。因此,产生了可见性问题。
有序性
有序性问题的原因是程序在执行时,可能会进行指令重排,重排后的指令与原本的顺序未必一致。
串行执行的线程不存在指令重排问题,但是多线程间可能会存在,且是否发生指令重排不可预见。
为什么会发生指令重排
之所以发生指令重排,完全是出于性能考虑。一条指令执行是可以分为很多步骤,如下
- 取址IF
- 译码和取寄存器操作数ID
- 执行或者有效地址计算EX
- 存储器访问MEM
- 写回WB
在CPU实际工作中,汇编指令也需要多个步骤依次执行。由于每个步骤都可能使用不同的硬件来完成,如取址时用到PC寄存器或者存储器。执行时用到ALU(算术逻辑单元)。为了提高性能,发明了流水线技术来执行指令。
可以看出,当第二条指令执行时,指令一并未执行完成,有了流水线,CPU才能真正高效的执行。但是,流水线总是害怕被中断。流水线满载时,性能确实相当不错,但是 一旦中断,所有的硬件设备都会进入一个停顿期,再次满载又需要几个周期。因此,性能损失就很大,所以,必须想办法尽量不让流水线中断。之所以需要指令重排,就是为了尽量减少中断流水线。
示例如下:
执行操作
a = b+c;
d = e-f;
指令重排前执行过程
由于ADD、SUB操作都需要等待上一条指令的结果,因此,在这里插入了不少停顿。通过将LW Rf,f和LW Re,e移动到前面执行即可。因为先加载e和f对程序是没有影响的,既然在Add的时候要停顿一下,那么停顿的时间不如去做点有意义的事情,指令重排后如下:
由此可见,指令重排对于CPU处理性能是十分必要的。
哪些指令不能重排:Happen-Before规则
Java虚拟机和执行系统会对指令进行一定的重排,但是指令重排是有原则的,并非所有的指令都可以随便改变执行位置。以下罗列了一些基本原则:
- 程序顺序原则:一个线程内保证语义的串行性。
- volatile原则:volatile变量的写先于读发生,这保证了volatile变量的可见性(
当一个线程修改volatile变量时,新的值会被立即刷新到主内存中,并且其他线程能够立即看到这个更新
) - 锁规则:解锁必然发生在随后的加锁前。
- 传递性:A先于B,B先于C,那么A必然先于C。
- 线程的start()方法先于他的每一个动作。
- 线程的所有操作先于线程的终结(Thread.join())
- 线程的中断先于被中断线程的代码
- 对象的构造函数的执行、结束先于finalize()方法。
相关文章:

Java高并发理论基础
并发级别 由于临界区的存在,多线程之间的并发必须受到控制。根据控制并发的策略,我们可以把并发的级别分为 阻塞、无饥饿、无障碍、无锁、无等待 几种。 阻塞 一个线程是阻塞的,那么在其他线程释放资源之前,当前线程无法继续执…...

Spring事件机制
文章目录 一、Spring事件二、实现Spring事件1、自定义事件2、事件监听器2.1 实现ApplicationListener接口2.2 EventListener2.3 TransactionalEventListener 3、事件发布4、异步使用 三、EventBus1、事件模式2、EventBus三要素3、同步事件3.1 定义事件类3.2 定义事件监听3.3 测…...
vue+canvas音频可视化
1.代码 <template><div class"subGuide"><canvas id"canvas"></canvas><br><audio id"audio" src"./audio.mp3" controls></audio></div> </template><script> export…...
俊昭stm32笔记
stm32——中断优先级 stm32——创建基础工程模板stm32——创建基础工程模板-CSDN博客 stm32——MCU启动方式stm32——MCU启动方式_stm32调试时程序启动方式-CSDN博客 stm32——串口stm32——串口_stm32 串口-CSDN博客 stm32——lcd液晶显示stm32——lcd液晶显示-CSDN博客...

W30-python03-pytest+selenium+allure访问百度网站实例
此篇文章为总结性,将pystest、selenium、allure结合起来 功能如下,web自动化,输入baidu网站,搜索“雷军”、打开网页中第一条内容 pytestsel.py如下: import time import re import allure import pytest from tools…...
如何在 Debian 8 上安装和使用 PostgreSQL 9.4
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 简介 关系型数据库是满足多种需求的数据组织的基石。它们支持从在线购物到火箭发射等各种应用。PostgreSQL 是一种历史悠久但仍然活跃的…...
【微信小程序】微信小程序设置本地背景图片在真机无法显示的解决方案
微信小程序设置本地背景图片在真机无法显示的解决方案 在开发微信小程序时,很多开发者会遇到一个常见的问题:在调试环境中设置本地背景图片可以正常显示,但在真机上却无法显示。本文将详细探讨这一问题的原因,并提供三种解决方案…...

Arthas在线诊断案例实战整理
Arthas - Java 应用诊断利器 Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法…...

使用 XRDP 远程linux主机
一、简介 XRDP是一个开源的远程桌面协议(Remote Desktop Protocol,RDP)服务器,采用的是标准的RDP。 官网地址:https://www.xrdp.org/ github地址: https://github.com/neutrinolabs/xrdp/releases XRDP也是C/S架构&…...

学习小型gpt源码(自用)
数据集构建_哔哩哔哩_bilibili (b站上有一系列课,从数据处理到模型构建和训练使用) 什么是batch? 为什么一个batch内的句子要一样长? 不同batch的长度可以不一样,但是同一个batch内长度一样!…...
@Transactional使用的注意事项
在项目中涉及到CRUD操作时,一般都会在方法上添加该注解,以为加上Transactional,Spring就可以自动帮我们进行事务的开启、提交 有一个很多人都会犯的误区: 将Spring事务与Transactional划上了等号,只要有数据库相关操作…...

快手可灵视频生成大模型全方位测评
快手视频生成大模型“可灵”(Kling),是全球首个真正用户可用的视频生成大模型,自面世以来,凭借其无与伦比的视频生成效果,在全球范围内赢得了用户的热烈追捧与高度评价。截至目前,申请体验其内测…...

【JavaScript】`Map` 数据结构
文章目录 一、Map 的基本概念二、常见操作三、与对象的对比四、实际应用场景 在现代 JavaScript 中,Map 是一种非常重要且强大的数据结构。与传统的对象(Object)不同,Map 允许您使用各种类型的值作为键,不限于字符串或…...
Ubuntu22.04使用NVM安装多版本Node.js和版本切换
Fabric官方目前支持Node.js开发区块链应用,建议使用Node长期支持版本(LTS)。 建议使用NVM安装Node.js,NVM可以帮助我们方便的在Node的不同版本之间进行切换,这样我们就可以同时工作在不同的项目上。 下面是安装的脚本…...

基于C51和OLED12864实现Goole小恐龙
在数字娱乐领域,Google小恐龙(T-Rex Runner)以其简单而上瘾的游戏机制赢得了广泛的关注和喜爱。这款内置于Chrome浏览器的离线小游戏,不仅为用户带来了乐趣,也激发了开发者们对其进行各种创新和扩展的灵感。本文将介绍…...

【Docker】CentOS7环境下的安装
环境展示 安装 配置仓库 sudo yum install -y yum-utils # docker官方key文件下载 sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 建议使用阿里云key文件下载 sudo yum-config-manager --add-repo https://mirrors.aliyun.…...

浏览器的最大并发数(http1.1)
HTTP/1.1:每个资源请求通常需要单独的TCP连接,尽管支持Keep-Alive机制,允许在同一个TCP连接上连续发送多个请求。但通常浏览器限制并发TCP连接数(例如,每个域名最多6个并发连接)。 HTTP/2:引入…...
Android 开发中px、dpi 和 dp三个单位的介绍
Android 开发中px、dpi 和 dp三个单位的介绍 在 Android 开发中,px、dpi 和 dp 是用来描述屏幕尺寸和密度的单位,它们在设计和开发中有着不同的作用和用途。 1. px(像素) 定义: px 表示屏幕上的一个像素点,…...

zookeeper开启SASL权限认证
目录 一、SASL介绍 二、使用 SASL 进行身份验证 2.1 服务器到服务器的身份验证 2.2 客户端到服务器身份验证 三、验证功能 一、SASL介绍 默认情况下,ZooKeeper 不使用任何形式的身份验证并允许匿名连接。但是,它支持 Java 身份验证与授权服务(JAAS)…...

mysql一个小问题引发的思考-mysql类型转换-查询缓存 及 MYSQL查询缓存以及自动选择不使用查询缓存的情况
一、mysql一个小问题引发的思考-mysql类型转换-查询缓存 最近在做的一个项目中有一个SQL语句发现点问题,大概如下: select * from table where cid0 or find_in_set(1, cid); 数据表中的字段cid是字符串类型,原来的后端同学未提过此字段还能是…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...

基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...

R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...