JVM - 高效并发
目录
Java内存模型和内存间的交互操作
Java内存模型
内存间的交互操作
内存间交互操作的规则
volatile特性
多线程中的可见性
volatile
指令重排原理和规则
指令重排
指令重排的基本规则
多线程中的有序性
线程安全处理
锁优化
锁优化之自旋锁与自适应自旋
锁优化之锁消除
锁优化之锁粗化
锁优化之轻量级锁
锁优化之偏向锁
JVM中获取锁的步骤
同步代码的基本规则
-
Java内存模型和内存间的交互操作
-
Java内存模型
- JCP定义了一种Java内存模型,以前是在JVM规范中,后来独立出来成为JSR-133(Java内存模型和线程规范修订)
- 内存模型:
- 在特定的操作协议下,对特定的内存或高速缓存进行读写访问的过程抽象
- Java内存模型主要关注JVM中把变量值存储到内存和从内存中取出变量值这样的底层细节
- 所有变量(共享的)都存储在主内存中,每个线程都有自己的工作内存
- 工作内存中保存该线程使用到的变量的主内存副本拷贝
- 线程对变量的所有操作(读、写)都应该在工作内存中完成
- 不同线程不能相互访问工作内存,交互数据要通过主内存
-
内存间的交互操作
- Java内存模型规定了一些操作来实现内存间交互,JVM会保证它们是原子的
- lock:锁定,把变量标识为线程独占,作用于主内存变量
- unlock:解锁,把锁定的变量释放,别的线程才能使用,作用于主内存变量
- read:读取,把变量值从主内存读取到工作内存
- load:载入,把read读取到的值放入工作内存的变量副本中
- use:使用,把工作内存中一个变量的值传递给执行引擎
- assign:赋值,把从执行引擎接收到的值赋给工作内存里面的变量
- store:存储,把工作内存中一个变量的值传递到主内存中
- write:写入,把store进来的数据存放进主内存的变量中
-
内存间交互操作的规则
- 不允许read和load、store和write操作之一单独出现,以上两个操作必须按顺序执行,但不保证连续执行
- 也就是说,read与load之间、store与write之间是可插入其它指令的
- 不允许一个线程丢弃它的最近的assign操作,即变量在工作内存中改变了之后必须把该变化同步回主内存
- 不允许一个线程无原因地(没有发生过任何assign操作)把数据从线程的工作内存同步回主内存中
- 一个新的变量只能从主内存中“诞生”,不允许在工作内存中直接使用一个未被初始化的变量
- 也就是对一个变量实施use和store操作之前,必须先执行过了assign和load操作
- 一个变量在同一个时刻只允许一条线程对其执行lock操作,但lock操作可以被同一个条线程重复执行多次,多次执行lock后,只有执行相同次数的unlock操作,变量才会被解锁
- 如果对一个变量执行lock操作,将会清空工作内存中此变量的值,在执行引擎使用这个变量前,需要重新执行load或assign操作初始化变量的值
- 如果一个变量没有被lock操作锁定,则不允许对它执行unlock操作,也不能unlock一个被其他线程锁定的变量
- 对一个变量执行unlock操作之前,必须先把此变量同步回主内存(执行store和write操作)
-
volatile特性
-
多线程中的可见性
- 可见性:就是一个线程修改了变量,其他线程可以知道
- 保证可见性的常见方法:volatile、synchronized、final(一旦初始化完成,其他线程就可见)
-
volatile
- volatile基本上是JVM提供的最轻量级的同步机制,用volatile修饰的变量,对所有的线程可见,即对volatile变量所做的写操作能立即反映到其它线程中
- 用volatile修饰的变量,在多线程环境下仍然是不安全的
- volatile修饰的变量,是禁止指令重排优化的
- 适合使用volatile的场景:
- 运算结果不依赖变量的当前值
- 或者能确保只有一个线程修改变量的值
-
指令重排原理和规则
-
指令重排
- 指的是JVM为了优化,在条件允许的情况下,对指令进行一定的重新排列,直接运行当前能够立即执行的后续指令,避开获取下一条指令所需数据造成的等待
- 线程内串行语义,不考虑多线程间的语义
- 不是所有的指令都能重排,比如:
- 写后读a = 1;b = a;写一个变量之后,再读这个位置
- 写后写a = 1;a = 2;写一个变量之后,再写这个变量
- 读后写a = b;b = 1;读一个变量之后,再写这个变量
- 以上语句不可重排,但是a = 1;b = 2;是可以重排的
-
指令重排的基本规则
- 程序顺序原则:
- 一个线程内保证语义的串行性
- volatile规则:
- volatile变量的写,先发生于读
- 锁规则:
- 解锁(unlock)必然发生在随后的加锁(lock)前
- 传递性:
- A先于B,B先于C那么A必然先于C
- 线程的start方法先于它的每一个动作
- 线程的所有操作先于线程的终结(Thread.join())
- 线程的中断(interrupt())先于被中断线程的代码
- 对象的构造函数执行结束先于finalize()方法
-
多线程中的有序性
- 在本线程内,操作都是有序的
- 在线程外观察,操作都是无序的,因为存在指令重排或主内存同步延时
-
线程安全处理
- 不可变是线程安全的
- 互斥同步(阻塞同步):synchronized、java.util.concurrent.ReentrantLock
- 目前这两个方法性能已经差不多了,建议优先选用synchronized
- ReentrantLock增加了如下特性:
- 等待可中断:
- 当持有锁的线程长时间不释放锁,正在等待的线程可以选择放弃等待
- 公平锁:
- 多个线程等待同一个锁时,须严格按照申请锁的时间顺序来获得锁
- 锁绑定多个条件:
- 一个ReentrantLock对象可以绑定多个condition对象,而synchronized是针对一个条件的,如果要多个,就得有多个锁
- 非阻塞同步:
- 是一种基于冲突检查的乐观锁的策略,通常是先操作,如果没有冲突,操作就成功了,有冲突再采取其它方式进行补偿处理
- 无同步方案:
- 其实就是在多线程中,方法并不涉及共享数据,自然也就无需同步了
-
锁优化
-
锁优化之自旋锁与自适应自旋
- 自旋:
- 如果线程可以很快获得锁,那么可以不在OS层挂起线程,而是让线程做几个忙循环,这就是自旋
- 自适应自旋:
- 自旋的时间不再固定,而是由前一次在同一个锁上的自旋时间和锁的拥有者状态来决定
- 如果锁被占用时间很短,自旋成功,那么能节省线程挂起、以及切换时间,从而提升系统性能
- 如果锁被占用时间很长,自旋失败,会白白耗费处理器资源,降低系统性能
-
锁优化之锁消除
- 在编译代码的时候,检测到根本不存在共享数据竞争,自然也就无需同步加锁了
- 通过-XX:+EliminateLocks来开启
- 同时要使用-XX:+DoEscapeAnalysis开启逃逸分析
- 所谓逃逸分析:
- (1)如果一个方法中定义的一个对象,可能被外部方法引用,称为方法逃逸
- (2)如果对象可能被其它外部线程访问,称为线程逃逸,比如赋值给类变量或者可以在其它线程中访问的实例变量
-
锁优化之锁粗化
- 通常都要求同步块要小,但一系列连续的操作导致对一个对象反复的加锁和解锁,这会导致不必要的性能损耗
- 这种情况建议把锁同步的范围加大到整个操作序列
-
锁优化之轻量级锁
- 轻量级是相对于传统锁机制而言,本意是没有多线程竞争的情况下,减少传统锁机制使用OS实现互斥所产生的性能损耗
- 其实现原理很简单,就是类似乐观锁的方式
- 如果轻量级锁失败,表示存在竞争,升级为重量级锁,导致性能下降
-
锁优化之偏向锁
- 偏向锁是在无竞争情况下,直接把整个同步消除了,连乐观锁都不用,从而提高性能
- 所谓的偏向,就是偏心,即锁会偏向于当前已经占有锁的线程
- 只要没有竞争,获得偏向锁的线程,在将来进入同步块,也不需要做同步
- 当有其它线程请求相同的锁时,偏向模式结束
- 如果程序中大多数锁总是被多个线程访问的时候,也就是竞争比较激烈,偏向锁反而会降低性能
- 使用-XX:-UseBiasedLocking来禁用偏向锁,默认开启
-
JVM中获取锁的步骤
- 会先尝试偏向锁;然后尝试轻量级锁
- 再然后尝试自旋锁
- 最后尝试普通锁,使用OS互斥量在操作系统层挂起
-
同步代码的基本规则
- 尽量减少锁持有的时间
- 尽量减小锁的粒度
相关文章:

JVM - 高效并发
目录 Java内存模型和内存间的交互操作 Java内存模型 内存间的交互操作 内存间交互操作的规则 volatile特性 多线程中的可见性 volatile 指令重排原理和规则 指令重排 指令重排的基本规则 多线程中的有序性 线程安全处理 锁优化 锁优化之自旋锁与自适应自旋 锁优…...

中小学智慧校园电子班牌系统源码 Saas云平台模式
智慧电子班牌区别于传统电子班牌,智慧校园电子班牌系统更加注重老师和学生的沟通交流和及时数据交互。学校为每个教室配置一台智能电子班牌,一般安装于教室门口,用来实时显示学校通知、班级通知,可设置集中分布式管理,…...

记录一次服务器被攻击的经历
突然收到阿里云发过来的异常登陆的信息: 于是,急忙打开电脑查看对应的ECS服务器的记录: 发现服务器的cpu占用率异常飙升,所以可以大概断定服务器已经被非法入侵了。 通过自己的账号登陆后,发现sshd服务有异常的链接存…...
Python解题 - CSDN周赛第29期 - 争抢糖豆
本期问哥是志在必得,这本算法书我已经觊觎许久,而之前两次因为种种原因未能如愿。因此,问哥这几天花了不少时间,把所有之前在每日一练做过的题目重新梳理了一遍。苦心人,天不负,感谢官方大大! 第…...

C代码中访问链接脚本中的符号
一、目的在之前的《GNU LD脚本命令语言(一)》、《GNU LD脚本命令语言(二)》我们介绍了GNU链接脚本的知识点,基本上对链接脚本中的SECTION、REGION、以及加载地址与执行地址的关系等内容有了一定的了解。本篇主要讲解链…...

MySQL 8:MySQL索引
索引就是通过一定的算法建立数据模型,用于快速查找某一列中具有特定值的行。如果没有索引,MySQL 必须从第一条记录开始读取整个表,直到找到相关的表。表越大,查询数据所花费的时间就越多。如果表中查询的列有索引,MySQ…...

JVM详解
一,JVM 1,JVM区域划分 类装载器,运行时数据区,字节码执行引擎 2,JVM内存模型(运行时数据区) 由本地方法栈,虚拟机栈,堆,方法区,和程序计数器组成。…...

MySQL数据库调优————索引数据结构
B-TREE B-TREE数据结构 B-TREE特性 根节点的子结点个数2 < X < m,m是树的阶 假设m 3,则根节点可有2-3个孩子 中间节点的子节点个数m/2 < y < m 假设m 3,中间节点至少有2个孩子,最多3个孩子 每个中间节点包含n个关…...

visual studio 改变界面语言
在使用visual studio 2019 时,开始是英文界面,后面变成了中文界面。但是看视频教学时有的是英文界面,我就想回到英文界面,所以有切换界面语言的需要。其实操作很简单:工具-> 选项 打开界面在界面里选择环境…...
2023.2.16每日一题——1250. 检查「好数组」
每日一题题目描述解题核心解法一:数论题目描述 题目链接:1250. 检查「好数组」 给你一个正整数数组 nums,你需要从中任选一些子集,然后将子集中每一个数乘以一个 任意整数,并求出他们的和。 假如该和结果为 1&#x…...

亿级高并发电商项目-- 实战篇 --万达商城项目 八(安装FastDFS、安装Nginx、文件服务模块、文件上传功能、商品功能与秒杀商品等功能)
专栏:高并发---分布式项目 👏作者简介:大家好,我是小童,Java开发工程师,CSDN博客博主,Java领域新星创作者 📕系列专栏:前端、Java、Java中间件大全、微信小程序、微信支…...

Viper捐款7000万韩元,合计人民币是多少钱?
Viper捐款7000万韩元,合计人民币是多少钱? #2023LCK春季赛##英雄联盟# #Viper捐款7000万韩元# Viper向大田东区捐款 7000 万,成为大田荣誉协会 105 号会员。Viper选手从 2019 年开始一直向大田东区捐款,但是他不希望这件事被公开…...

前端vue实现系统拦截跳转外链并进入跳转询问界面
跳转询问界面如下图所示: 给自己挖坑的实现方式,最终解决方案请看最底下 思路:正常情况下我们有2种方式跳转外链 第一种非a标签,我们手动添加事件进行跳转 <div class"dingdan public-padding p-item" click&quo…...
【Linux】Shell(Bash)单引号、双引号、不加引号和反引号用法和区别详解
简要总结 不加引号:不会将含有空格的字符串视为一个整体输出, 如果内容中有变量等,会先把变量解析出结果,然后在输出最终内容来,如果字符串中带有空格等特殊字符,则不能完整的输出,需要改加双引号ÿ…...

本人使用的idea插件
文章目录🚏 本人使用的idea插件🚬 pojo to Json🚬 GsonFormatPlus🚬 EasyYapi🚬 Chinese (Simplified) Language Pack / 中文语言包🚬 MyBatis Log Free🚬 MyBatisPlusX🚬 Statistic…...

站在行业C位,谷医堂打开健康管理服务新思路
对于农村及贫困地区老百姓来说,由于交通因素和家庭经济条件制约,看病难致身体调理情况一直不太乐观,这也导致心理压力很大。然而,随着近年中医药产业崛起与快速发展,这种局面很快就会得到改观,以湖南谷医堂…...

ABO溶血症概率
[简介]ABO溶血是由于母亲和胎儿ABO血型不合引起的新生儿溶血,概率不是很大,一般出现在准妈妈是O血,准爸爸是非O血,这次容易发生血型不合,但新生儿ABO溶血概率不高,大多数症状相对较轻。ABO溶血的概率是什么…...
【算法数据结构体系篇class03】:数组、链表、栈、队列、递归时间复杂度、哈希表、有序表问题
一、反转链表package class03;import java.util.ArrayList; import java.util.List;/*** 链表反转*/ public class ReverseLinkedList {public static class Node {public int value;public Node next;public Node(int data) {value data;}}public static class DoubleNode {p…...
【新2023】华为OD机试 - 最多提取子串数目(Python)
最多提取子串数目 题目 给定由 [a-z] 26 个英文小写字母组成的字符串 A 和 B,其中 A 中可能存在重复字母,B 中不会存在重复字母 现从字符串 A 中按规则挑选一些字母,可以组成字符串 B。 挑选规则如下: 1) 同一个位置的字母只能被挑选一次 2) 被挑选字母的相对先后顺序不…...
嵌入式C语言设计模式 --- 代理模式
1 - 什么是代理模式? 代理模式(Proxy Pattern),是指当客户端无法访问某个对象或者访问某个对象存在困难的时候,可以通过一个代理对象来进行间接访问。 举一个生活中的例子,比如,我们在买火车票或者飞机票的时候,有时候不会直接在12306或者航空公司官网上面购买,而是…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...

有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...

嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)
目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 编辑编辑 UDP的特征 socke函数 bind函数 recvfrom函数(接收函数) sendto函数(发送函数) 五、网络编程之 UDP 用…...
DiscuzX3.5发帖json api
参考文章:PHP实现独立Discuz站外发帖(直连操作数据库)_discuz 发帖api-CSDN博客 简单改造了一下,适配我自己的需求 有一个站点存在多个采集站,我想通过主站拿标题,采集站拿内容 使用到的sql如下 CREATE TABLE pre_forum_post_…...
32单片机——基本定时器
STM32F103有众多的定时器,其中包括2个基本定时器(TIM6和TIM7)、4个通用定时器(TIM2~TIM5)、2个高级控制定时器(TIM1和TIM8),这些定时器彼此完全独立,不共享任何资源 1、定…...
Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解
文章目录 1. 题目描述1.1 链表节点定义 2. 理解题目2.1 问题可视化2.2 核心挑战 3. 解法一:HashSet 标记访问法3.1 算法思路3.2 Java代码实现3.3 详细执行过程演示3.4 执行结果示例3.5 复杂度分析3.6 优缺点分析 4. 解法二:Floyd 快慢指针法(…...

Canal环境搭建并实现和ES数据同步
作者:田超凡 日期:2025年6月7日 Canal安装,启动端口11111、8082: 安装canal-deployer服务端: https://github.com/alibaba/canal/releases/1.1.7/canal.deployer-1.1.7.tar.gz cd /opt/homebrew/etc mkdir canal…...