JVM(6)

JMM

JVM定义了一种Java内存模型来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果.在此之前,C/C++直接使用物理硬件和操作系统的内存模型,因此,会由于不同平台下的内存模型差异,有可能导致程序在一套平台上并发完全正常,而在另一套平台上并发访问经常出错.

主内存和工作内存

Java内存模型的主要目标是定义程序中各个变量的访问规则,即在JVM中将变量存储到内存和从内存中取出变量这样的底层细节. 此处的变量包括实例字段,静态字段和构成数组对象的元素,但不包括局部变量和方法参数,因为后两者是线程私有的,不会被线程共享.

Java内存模型规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存中保存了被该线程使用到的变量的主内存副本拷贝,线程对变量的所有操作(读取/赋值等)都必须在工作内存中进行,而不能直接读写主内存中的变量.不同线程之间也无法直接访问对方工作内存中的变量,线程间变量值的传递均需要通过主内存来完成.线程,主内存,工作内存三者的交互关系如下所示:

内存间的交互操作

关于主内存与工作内存之间的具体交互协议,即一个变量如何从主内存拷贝到工作内存,如何从工作内存同步回主内存之类的实现细节,Java内存模型中定义了如下8种操作来完成.JVM实现时必须保证下面提及的每一种操作是原子的,不可再分的.

 lock(锁定):作用于主内存的变量,它把一个变量标识为一条线程独占的状态.

unlock(解锁):作用于主内存的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可以被其它线程锁定.

read(读取):作用于主内存的变量,它把一个变量的值从主内存传输到线程的工作内存中,以便随后load动作使用.

load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中.

use(使用):作用于工作内存中的变量,它把工作内存中一个变量值传递给执行引擎.

assign(赋值):作用于工作内存中的变量,它把一个从执行引擎接收到的值赋给工作内存变量.

store(存储):作用于工作内存中的变量,它把工作内存中一个变量的值传送到主内存中,以便后续write操作的使用.

write(写入):作用于主内存中的变量,它把store操作从工作内存中得到变量的值放入主内存的变量中.

 Java内存模型的三大特性:

原子性:由Java内存模型来直接保证的原子性变量操作包括read, load, assign, use, store和read.大致可以认为,基本数据类型的访问读写是具备原子性的.如果需要更大范围的原子性,需要synchronized关键字约束.(即一个操作或者多个操作要么全部执行并且执行的过程不会被任何因素打断,要么都不执行).

可见性:可见性是指当一个线程修改了共享变量的值,其它线程能够立即得知这个修改.volatile,synchronized,final三个关键字可以实现可见性.

有序性:如果在本线程内观察,所有的操作都是有序的;如果在线程中观察另一个线程,所有的操作都是无序的.前半句是指"线程内表现为串行",后半句是指"指令重排序"和"工作内存和主内存同步延迟现象".

Java内存模型具备一些先天的"有序性",即不需要通过任何手段就能够得到保证的有序性,这个通常也称为happens-before原则.如果两个操作的执行次序无法从happens-before原则推导出来,那么它们就不能够保证它们的有序性,虚拟机可以随意地对它们进行重排序.

下面就来具体介绍一下happens-before原则(现行发生原则):

程序次序规则:一个线程内,按照代码顺序,书写在前面的操作现行发生于书写在后面的操作.

锁定规则:一个unLock操作先行发生于后面对同一个锁的lock操作.

volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作.

传递规则:如果操作A现行发生于操作B,而操作B又现行发生于操作C,则可以得出操作A现行发生于操作C

线程启动规则:Thread对象的start()方法先行发生于此线程的每一个动作.

线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码.

线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束,Thread.isAlive()的返回值手段检测到线程已经终止运行.

对象终结规则:一个对象的初始化完成先行于它的finalize()方法(用于在对象被垃圾回收器回收之前执行一些清理操作)的开始. 

也就是说,想要并发程序正确地执行,必须要保证原子性,可见性以及有序性.只要有一个没有被保证,就有可能会导致程序运行不正确

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/424815.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

多输入多输出 | MATLAB实现GWO-Elman灰狼优化循环神经网络多输入多输出预测

多输入多输出 | MATLAB实现GWO-Elman灰狼优化循环神经网络多输入多输出预测 目录 多输入多输出 | MATLAB实现GWO-Elman灰狼优化循环神经网络多输入多输出预测预测效果基本介绍程序设计往期精彩参考资料 预测效果 基本介绍 Matlab实现GWO-Elman灰狼优化循环神经网络多输入多输出…

手把手教测试,全网内容最全有深度-jmeter-Flow Control Action

5.1.7.6.Flow Control Action(测试活动) Logical Action on Thread: Pause 暂停,配合 Duration 一起使用;Duration(milliseconds) 延迟时间,单位是毫秒 Start Next Thread Loop 开始本线程下一次循环 设置线程组线程数2&#xff…

(资源篇)2025届暑假实习春招全攻略路线

绝对的全攻略,资源完善程度绝对的全网唯一。 觉得有帮助的:随手一键三连关注就是对up主最大的激励。 绝对的宝藏up主!!!,up主每天都会进行更新视频,算法视频or校招信息or八股讲解。 【暴躁老…

位运算第二弹

力扣191.位1的个数 public class Solution {// you need to treat n as an unsigned valuepublic int hammingWeight(int n) {int ret0;while(n!0){n(n&n-1);ret;}return ret;} } 推荐是自己去手动推一下,深刻理解一下,什么叫做最右侧的1。 力扣338.…

在docker中搭建selenium 爬虫环境(3分钟快速搭建)

1、安装docker 省略 2、拉取镜像 docker pull selenium/standalone-chrome-debug 3、运行容器 docker run -d -p 4444:4444 -p 5900:5900 -v C:\Users\Public\VNC_Donwnloads:/home/seluser/Downloads --memory6g --name selenium_chrome selenium/standalone-chrome-debu…

[VulnHub靶机渗透] CONNECT THE DOTS

🍬 博主介绍👨‍🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~ ✨主攻领域:【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】 🎉点赞➕评论➕收藏 …

《秦时明月》IP新高度:与陕西历史博物馆共同书写文化传承新篇章!

在IP产业风起云涌的今天,如何以创意和匠心为传统文化注入新的活力,成为了摆在每一位文化工作者面前的重要课题。近日,《秦时明月》作为一部深受观众喜爱的国产动画IP,在迎来其十七周年之际,联手陕西历史博物馆&#xf…

字符函数和字符串函数(下)

个人主页(找往期文章包括但不限于本期文章中不懂的知识点):我要学编程(ಥ_ಥ)-CSDN博客 目录 strncpy函数的使用 函数原型: strncpy的使用 strncat函数的使用 函数原型: strncat的使用 strncmp函数的使用 函…

Vue开发实例(三)项目引入Element-UI

项目引入Element-UI 一、引入Element-UI二、注册组件1、vue2使用element-ui2、vue3使用element-ui 三、使用Element组件1、轻微改造2、验证element是否生效 一、引入Element-UI npm i element-ui --save npm install element-ui -S等待安装完成 二、注册组件 1、vue2使用ele…

Redis缓存示例【一篇看懂数据库缓存的技术redis】

Redis缓存示例【一篇看懂数据库缓存的技术redis】 环境准备缓存短信验证码缓存菜品信息 因为服务器和数据库直接读写,性能消耗大 我们可以用redis缓存 当服务器想访问数据库时,可以先访问redis,看是否之前访问过想要的数据,这样就…

51单片机-(中断系统)

51单片机-(中断系统) 了解51单片机中断系统、中断源、中断响应条件和优先级等,通过外部中断0实现按键控制LED亮灭为例理解中断工作原理和编程实现过程。 1.中断系统结构 89C51/52的中断系统有5个中断源 ,2个优先级,…

【yolov8部署实战】VS2019+OpenCV环境部署yolov8目标检测模型|含详细注释源码

一、前言 之前一阵子一直在做的就是怎么把yolo项目部署成c项目,因为项目需要嵌套进yolo模型跑算法。因为自己也是本科生小白一枚,基本上对这方面没有涉猎过,自己一个人从网上到处搜寻资料,写代码,调试,期间…

Trie树(1.字符串统计____2.最大异或对求解)

Trie树 文章目录 Trie树Trie字符串统计正解 最大异或对1.暴力 (可以过6/10个测试点)2. Trie树模拟 用法:高效地存储和查找字符串集合的数据结构 存储形式: 将n个单词各个字符进行枚举,若是(根节点所指向包含字符c&…

【javaSE-语法】lambda表达式

【javaSE-语法】lambda表达式 1. 先回忆一下:1.1 接口不能直接通过关键字new进行实例化1.2 函数式接口1.3 匿名内部类1.31 匿名内部类在代码中长啥样?1.32 构造一个新的对象与构造一个扩展了某类的匿名内部类的对象,两者有什么区别&#xff1…

基于vue-office实现docx、xlsx、pdf文件的在线预览

概述 在做项目的时候会遇到docx、xlsx、pdf等文件的在线预览需求,实现此需求可以有多种解决方式,本文基于vue-office实现纯前端的文件预览。 效果 如下图,分别为docx、xlsx、pdf三种类型的文件在线加载后的效果。你也可以访问官方预览网址…

【CSP试题回顾】202312-2-因子化简

CSP-202312-2-因子化简 解题思路 本题要求实现的是素数分解,并检查每个素因子的指数是否大于等于k,满足条件则将其加入最终乘积中,最后输出这个乘积。如果没有任何素因子的指数大于等于k,则按照题目要求输出1。 输入测试用例数q&…

ESP32如何查看IIC等默认引脚?

在通过ESP32做项目的时候,用到了IIC,但是在查看芯片手册的时候,上面说又有引脚都可以作为IIC引脚 看到这个的时候,人麻了。当时只想着省事,想使用默认引脚,后来在寻找芯片库文件的时候,发现了&…

云计算与大数据课程笔记(一)云计算背景与介绍

如何实现一个简易搜索引擎? 实现一个简易的搜索引擎可以分为几个基本步骤:数据收集(爬虫)、数据处理(索引)、查询处理和结果呈现。下面是一个概括的实现流程: 1. 数据收集(爬虫&am…

数据结构 - Trie树(字符串统计、最大异或对)

文章目录 前言Part 1:Trie字符串统计1.题目描述输入格式输出格式数据范围输入样例输出样例 2.算法 Part 2:最大异或对1.题目描述输入格式输出格式数据范围输入样例输出样例 2.算法 前言 本篇博客将介绍Trie树的常见应用,包括:Trie…

Java 中对包含关系的判断

本文将为您详细讲解 Java 中对包含关系的判断,包括数组、字符串等,并提供相应的代码例子。 1. 数组包含关系判断 在 Java 中,数组包含关系判断通常使用循环来实现。以下是几种常见的判断方法: 示例 1:使用 for…