0

0

JAVA虚拟机(JVM)详细介绍(八)——高效并发

王林

王林

发布时间:2019-08-24 17:25:48

|

2500人浏览过

|

来源于CSDN

转载

20190622102535946.png

内存模型

内存模型是在特定的操作协议下,对特定的内存或高速缓存进行读写访问的过程抽象。其主要目标是定义程序中各个变量的访问规则。

主内存和工作内存

20190622103148678.jpg

所有的变量都存储在主内存中,每条线程还有自己的工作内存,其工作内存中是被线程使用到的变量的主内存副本拷贝,线程对变量的读取、赋值等操作都必须在工作内存中进行,而不能直接读取主内存中的变量。

立即学习Java免费学习笔记(深入)”;

内存间交互操作

从主内存拷贝到工作内存:顺序地执行read和load操作。
工作内存同步到主内存:store和write操作。

volatile的特性

Volatile的作用和synchronized相同,但是和synchronized相比,更轻量。其特性主要有如下两点:

保证此变量对所有线程的可见性

啥意思呢?指当一个线程修改了这个变量的值,新值对于其他线程来说是立即可知的。而普通变量做不到这一点,普通变量的值在线程间传递均需要通过主内存来完成,比如线程A修改了一个普通变量的值,然后向主内存进行回写,另外一条线程B在线程A回写完成了之后再从主内存进行读取操作,新变量值才会对线程B可见。

禁止指令重排序优化

因为指令重排序会干扰程序的并发执行。

多线程

为什么需要多线程?

计算机的运算速度与它的存储和通信子系统速度的差距太大,大量的时间都花费在磁盘I/O、网络通信、数据库访问上了。使用多线程能更好地利用cpu。

有哪些并发应用场景?

充分利用计算机处理器

一个服务端同时对多个客户端提供服务

如何使处理器内部的运算单元被充分利用?

加入一层高速缓存

将运算需要使用到的数据复制到缓存中,让运算能快速进行。当运算结束后再从缓存同步回内存中,这样处理器就无须等待缓慢的内存读写了。不过这个要考虑一个问题:怎么保证缓存的一致性。

20190622104629877.jpg

对输入代码进行乱序执行优化

线程的实现方式

使用内核线程实现

内核线程就是直接由操作系统内核支持的线程。

使用用户线程实现

用户线程的建立、同步、销毁和调度完全在用户态中完成,不需要内核的帮助,内核也感知不到线程存在的实现。这种实现方式使用较少。

使用用户线程加轻量级进行混合实现

合并到一起

线程调度

线程调度是指系统为线程分配处理器使用权的过程。主要分为两种:协同式和抢占式。

协同式

线程的执行时间由线程本身来控制,线程把自己的工作执行完了,会主动通知系统切换到另外一个线程上。
其优点是实现简单,而且没有线程同步的问题。缺点是如果一个线程编写有问题,一直不告诉系统进行线程切换,那程序就会一直阻塞在那里,容易导致系统崩溃。

抢占式

线程将由系统来分配执行时间,线程切换不由本身来决定。java使用的线程调度方式就是这种。

线程安全

当多个线程访问一个对象时,如果不考虑这个线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其它的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象就是安全的。

共享数据的分类

AI小聚
AI小聚

一站式多功能AIGC创作平台,支持AI绘画、AI视频、AI聊天、AI音乐

下载

不可变

不可变的共享数据是用final修饰的数据,其一定是线程安全的。如果共享数据是一个基本类型变量,那么只要在定义的时候使用final关键字即可。

如果共享数据是一个对象,那就需要对象的行为不会对其状态产生影响,可以将对象中带有状态的变量都声明为final。比如String类就是一个不可变类

绝对线程安全

在Java API中标注自己是线程安全的类,大多数都不是绝对的线程安全。比如Vector是一个线程安全的集合,它的所有的方法都被修饰成同步,但是在多线程的环境中,它依旧不是同步的。

相对线程安全

相对线程安全就是我们通常意义上所说的线程安全,它只能保证对这个对象单独操作是线程安全的。但是对于一些特定顺序的连续调用,就可能需要在调用端使用额外的同步手段来保证调用的正确性。
大部分的线程安全类都属于这种类型。

线程兼容

对象本身不是线性安全的,但可以通过在调用端正确地使用同步手段来保证对象在并发环境中可以安全的使用。大部分的不是线程安全的类,都属于这种类型。

线程对立

无论怎样,都不能在多线程环境中并发使用,如System.setIn()、System.SetOut()。一个对输入进行修改,一个对输出进行修改,两者是不能“交替”进行的。

实现方法

方式一:互斥同步——悲观并发策略

(1)synchronized

其原理是:这个关键字在经过编译后,会在同步块的前后分别形成monitorenter和monitorexit这两个字节码指令。当执行monitorenter指令时,程序会尝试获取对象的锁,如果能获取到,则把锁的计数器+1,相应的,在执行monitorexit时,会将锁计数器-1。当计数器为0时,锁就被释放。

其特点是:对同一条线程来说是可重入的;同步块在已进入的线程执行完之前,会阻塞后面的其他线程进入。

其选用场景是:在确实必要的情况下才使用此,因为其是重量级的。

(2)ReentrantLock

此重入锁是java.util.concurrent(JUC)包下的类。其高级特性有:等待可中断、可实现公平锁、锁可以绑定多个条件。

方式二:非阻塞同步——乐观并发策略

先进行操作,如果没有其它线程争用共享数据,那操作就是成功了;如果共享数据有争用,产生了冲突,那就再采取其它的补偿措施。

方式三:无同步方案

如果一个方法本来就不涉及共享数据,那就没有必要进行同步措施。比如可重复代码和线程本地存储。

(1)可重入代码

如果一个方法,它的返回结果是可预测的,只要输入了相同的数据,就都能返回相同的结果,那它就满足可重入的要求。

(2)线程本地存储

如果一段代码中所需要的数据必须与其它代码共享,而且这些共享数据的代码在同一个线程中执行,如此,我们可以把共享数据的可见范围限制在一个线程中,这样,就不用同步也能保证线程之间不出现数据争用问题。

锁优化

适应性自旋

因为阻塞或者唤醒一个JAVA的线程需要操作系统切换CPU状态来完成,这种状态的转换需要耗费处理器时间。如果同步代码块中的内容过于简单,很可能导致状态转换消耗的时间比用户代码执行的时间还要长。

为了解决这个问题,我们可以让后面请求锁的线程“稍等一下”,执行一个忙循环,进行自旋。此时没有放弃处理器的执行时间。如果自旋超过了限定的次数,仍然没有成功获得锁,那就会使用传统的方式去挂起线程了。

 那什么叫做适应性自旋呢?

就是在同一个锁对象上,如果自旋等待刚刚成功获得过锁,那虚拟机就会认为这次自旋获得锁的概率挺大,就会允许其自旋等待持续相对更长的时间。相反,如果自旋很少成功获得过锁,则可能省略掉自旋过程。

锁消除

指虚拟机即时编译器在运行时,对一些代码上要求同步,但是被检测到不可能存在共享数据竞争的锁进行消除。

锁粗化

如果一系列的连续操作都对同一个对象反复加锁和解锁,甚至加锁操作是出现在循环体中的,那即使没有线程竞争,频繁地进行互斥同步操作也会导致不必要的性能损耗。
如果虚拟机探测到一串零碎的操作都对同一个对象加锁,将会把加锁同步的范围粗化到整个操作序列的外部,这样只需要加锁一次就够了。

轻量级锁

在没有多线程竞争的前提下,减少传统的重量级锁使用操作系统互斥量产生的性能损耗。
适用场景:无实际竞争,多个线程交替使用锁;允许短时间的锁竞争。

偏向锁

偏向锁用于减少无竞争且只有一个线程使用锁的情况下,使用轻量级锁产生的性能消耗。轻量级锁每次申请、释放锁都至少需要一次CAS,但偏向锁只有初始化时需要一次CAS。
适用场景:无实际竞争,且将来只有第一个申请锁的线程会使用锁。

以上是关于JAVA虚拟机中高效并发的详细介绍,更多相关问题请访问PHP中文网:JAVA视频教程

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1031

2023.08.02

c++中volatile关键字的作用
c++中volatile关键字的作用

本专题整合了c++中volatile关键字的相关内容,阅读专题下面的文章了解更多详细内容。

76

2025.10.23

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

765

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

377

2025.12.24

java多线程相关教程合集
java多线程相关教程合集

本专题整合了java多线程相关教程,阅读专题下面的文章了解更多详细内容。

32

2026.01.21

C++多线程相关合集
C++多线程相关合集

本专题整合了C++多线程相关教程,阅读专题下面的的文章了解更多详细内容。

29

2026.01.21

C# 多线程与异步编程
C# 多线程与异步编程

本专题深入讲解 C# 中多线程与异步编程的核心概念与实战技巧,包括线程池管理、Task 类的使用、async/await 异步编程模式、并发控制与线程同步、死锁与竞态条件的解决方案。通过实际项目,帮助开发者掌握 如何在 C# 中构建高并发、低延迟的异步系统,提升应用性能和响应速度。

103

2026.02.06

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

386

2023.06.29

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

37

2026.03.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号