深度学习Java之内存模型【译】

Java培训深度学习都要学什么   java的知识点有很多,如果是有java基础的同学,进行深度学习是非常有必要的,比较职场技能更新迭代非常的快,那么java培训深度学习都要学什么呢?来看看下面的详细介绍。   Java培训深度学习都要学什么?   Java深度学习要掌握两点:   第一个是基础。比如对集合类,并发包,类加载,IO/NIO,JVM,内存模型,泛型,异常,反射的学习掌握,在使用线程池时,因为使用了无界队列,在远程服务异常情况下导致内层飙升,怎么去解决?再举一例,由于对ThreadLocal理解出错,使用它做线程安全 阅读详情

0?wx_fmt=png

Java的内存模型定义了Java虚拟机如何和计算机物理内存进行交互。Java虚拟机是一体化的计算机模型,所以它自然也包含了内存模型。

如果你要设计运行稳健的并发程序,理解Java内存模型是非常必要的。Java内存模型定义了不同线程之间变量读写的可见行以及如何同步访问共享变量。

最原始的Java内存模型设计的很不足。后来到了Java1.5版本就重新制定了,这个版本的内存模型一直延续到了现在。

深入Java内存模型

Java内存模型内部分为线程堆栈和堆两种区域。下图粗略了表示了这种结构。

0?wx_fmt=jpeg

Java虚拟机中的每个线程都有它自己的运行堆栈。线程堆栈记录了当前线程到达当前执行点所经历的一系列方法调用信息。暂且把它称之为【调用栈】。随着线程不停地执行代码,调用栈一直不停的改变。

线程栈记录了正在运行的调用栈里所有方法的局部变量信息。线程只能访问它自己的线程栈。局部变量仅对创建它的线程有效,其它线程是完全看不见的。甚至当两个线程执行的是同一段代码逻辑,它们也会分别在自己的线程栈里创建这些局部变量,每个线程都有它自己的局部变量,互不干扰。

所有原生类型(boolean, byte, short, char, int, long, float, double)的局部变量都是完全存储在当前的线程栈里面,别的线程完全看不到。线程之间可以通过拷贝来分享原生类型的变量,但是无法直接共享。

堆包含了Java应用程序创建的所有对象,不管这些对象是被哪个线程创建的。这些对象包含了所有原生类型的包装类型。无论这些被创建的对象是被赋值给了哪个局部变量还是挂在了某个对象的成员变量上,它们都存储在堆里面。

下图展示了Java虚拟机里面的调用栈和局部变量以及存在堆里面的所有对象。

0?wx_fmt=jpeg

局部变量可以是原生类型,这样它就完全存在了栈里面。

局部变量也可以是对象的引用,这种情况下对象的引用也就是局部变量本身是存在栈里面的,而对象本身的内容则放在堆里面。

对象里有方法,这些方法又有局部变量。这些局部变量也存在栈里面,尽管这些方法所属的对象是放在堆里面的。

对象的所有字段同对象一样都是放在堆里的,不论这个字段是原生类型还是对象的引用类型。

静态变量和类定义对象一样也是放在堆里的。

堆里的对象可以被所有线程访问,只要这些线程有相应对象的引用。线程如果可以访问一个对象,那一定就可以访问这个对象的成员字段。如果两个线程同时访问同一个对象的同一个方法,那么它们会同时访问对象的字段,当时每个线程都会创建属于自己的局部变量。

具体请看下面这张图。

0?wx_fmt=jpeg

两个线程都有一些局部变量。其中局部变量2指向了堆里面的对象3。这两个线程都有属于自己的指向同一个对象的引用变量。这些引用都是局部变量,都存放在各自的线程栈上,尽管它们都指向同一个对象。

注意到这个共享的对象3持有对象2和对象4的引用作为它的内部成员。通过成员变量引用, 这两个线程都可以访问对象2和对象4。

图中两个线程栈里面的局部变量1分别指向了堆里的不同对象。理论上堆里的所有对象都可以被两个线程访问,但是就图上所示,每个线程都只有一个对象的引用。

上面这张图可以使用下面的代码来表示

0?wx_fmt=jpeg

如果两个线程同时执行run方法,就呈现出了上面那张图。run方法调用methodOne,methodOne又调用methodTwo。

methodOne定义了一个原生的局部变量和一个对象引用局部变量。两个线程在执行methodOne的时候都会在各自的栈上创建局部变量1和局部变量2,它们互不干扰,一个线程是看不到另外一个线程对局部变量做的任何修改的。

两个线程在执行methodOne时还会创建各自的局部变量2,然后这两个变量都指向堆里的同一个对象。代码设置局部变量2指向一个静态变量引用的对象,这个静态变量是唯一的,也存放在堆里。结果就是这两个局部变量都指向同一个又静态变量指向的ShareObject对象,ShareObject这个对象实例就存放在堆里,就是图中的对象3。

注意到MyShareObject的两个成员变量都是long类型的。因为它们是成员变量,所以也跟对象一起放在堆里。只有局部变量才会放在栈上。

硬件内存结构

现代的硬件内存结构和Java内存模型是不一样的。想要理解Java内存模型是如何同物理内存交互的话,先把硬件内存结构搞动非常重要。这一节我们来看看硬件内存结构,接下来我们再看Java内存模型是如何与之交互的。

看图

0?wx_fmt=jpeg

现代计算机一般都有多个CPU,每个CPU又有多个核。所以它们往往可以同时跑多个线程。每个CPU同一时间都可以跑一个线程。这就意味着如果你的Java程序是多线程的,每个CPU都会同时跑着一个线程。

每个CPU内部都有一堆基本的寄存器。CPU和这些寄存器交互要比和内存交互快得多。

每个CPU都有一个缓存层,现代的CPU一般都是特定大小的缓存层。CPU访问这些缓存要比访问内存快,但是还是比不上寄存器。有些CPU可能会有多个缓存层,不过这不影响我们理解Java内存模型是如何同内存进行交互的。我们只要知道CPU有这样一个缓存层就够了。

计算机的主内存所有的线程都可以访问,它的容量往往比CPU缓存打得多。

0?wx_fmt=jpeg

当CPU要读主内存时,它会首先读取一小块内存到CPU缓存里,接着又会读取缓存的一小块到寄存器里,然后就可以继续操作了。当CPU要写主内存时,它会将寄存器里的值Flush到缓存里,后面又回将缓存里的值Flush到主内存。

当CPU想用这些缓存存点别的什么东西时会先把缓存里的数据会刷回到主内存。CPU缓存可以在从主存加载数据的同时回写数据到主存,这两个操作对象是CPU缓存的不同部分。CPU缓存没必要一次性读写整个缓存区域。一般来说CPU缓存更新的单位是【缓存行】,英文是cache lines。一部分缓存行从主存加载数据,另一部分缓存行回写数据到主存。

Java内存模型和硬件内存结构的异同

前面提到,Java内存模型和硬件内存结构是不一样的。硬件内存结构是不会区分线程栈和堆的。在硬件上,线程栈和堆都放在主内存里,还有一些甚至会在CPU缓存和寄存器里。如下图所示

0?wx_fmt=jpeg

当对象和对象可以放在不同的存储地方的时候,问题就来了。

  1. 线程修改共享变量的可见性

  2. 读写共享变量的竞态条件

解下来我们逐个分析

共享对象的可见性

如果多个线程共享一个对象,而这个对象又没有使用volatile修饰也没有任何同步控制的话,一个线程对共享变量的修改是可能不会立即被其它线程看到的。

试想一开始对象是在主存里创建的,然后CPU将对象加载到CPU缓存,在缓存里修改了这个对象而没有立即将缓存写会主存。那这个修改过的对象是不能够被运行在其它CPU上的线程看到的。结果就是每个线程都有这个对象的一个拷贝,分别放在不同的CPU缓存里。

下图能很好的表现这种情况。运行在左边CPU上的线程将count变量加载到CPU缓存中,然后将count修改成了2,而右边CPU上跑的线程则看不到这种改变。因为修改过的缓存行没有同步刷回主内存。

0?wx_fmt=jpeg

为了解决这个问题就必须用到volatile关键字,volatile关键字会确保读操作会直接读取主内存,对变量的修改也是立即回写主内存。

竞态条件

多个线程共享一个对象,并且同时对这个对象进行修改的时候,竞态条件就产生了。

假设线程A将共享变量count读到CPU缓存,同时线程B也将共享变量count读到另一个不同的CPU缓存,然后同时对count进行加1操作,如此count变量被更新了2次。

如果这两个加1操作是串行执行的话,那么当count变量回写内存的时候,值就是value+2

可现在这两个操作没有进行适当的同步控制,也就是说不是串行的。不管是哪个线程先回写主存,最后的值总是value+1,而不是value+2。下面这张图显示了这种竞态条件。

0?wx_fmt=jpeg

解决这种问题,你可以使用Java的synchronized关键字。synchronized关键字保证同一时间只有一个线程可以进入临界区。同步块同样也可以保证块内的读变量都是直接读主存,变量修改在退出同步块的时候会立即回写到主存,不管这个变量有没有使用volatile修改都一样。

阅读更多相关文章,请关注微信公众号【码洞】

0?wx_fmt=jpeg

Java实现像素级语义分割:ONNX模型JVM原生部署实战 语义分割是计算机视觉中将图像中每个像素分配类别标签的核心任务,其本质是建立输入空间坐标到输出类别的显式映射函数。技术原理依赖编码器-解码器结构(如U-Net),通过多尺度特征提取与上采样恢复空间精度,输出为[H,W,C]三维张量。在工业场景中,该任务对内存确定性、低延迟和系统可审计性提出严苛要求,远超学术demo范畴。Java凭借可控的堆内存管理、零JNI调用和Spring Boot无缝集成能力,成为金融风控、工业质检等高可靠产线的优选平台。本文聚焦JVM原生推理路径,详解ONNX模型导出约束、DL4J内存 阅读详情

相关推荐

从零到一:YOLOv11高帧率模型在RDK X5上的ONNX转换与部署实战

本文详细介绍了将最新的YOLOv11高帧率模型部署到地平线RDK X5开发板的完整实战流程。内容涵盖从PyTorch模型导出ONNX、地平线工具链环境配置与模型量化编译,到编写高效的板端推理代码,并针对高帧率目标进行了后处理优化。通过实战避坑指南,帮助开发者在RDK X5上实现30FPS以上的实时目标检测。

weixin_29089057的博客 141

【深度学习】参数量、模型大小、显存

【深度学习】参数量、模型大小、显存对于一个深度学习神经网络来说,其通常包含很多卷积层,用于不断提取目标的特征,或对目标进行最终定位或者分类。 1 数据存储精度与存储空间 在深度学习神经网络中,最常见的数据格式是float32,占4个字节(Byte)。类似地,float16,占2个字节。1024个字节为1KB,1024x1024个字节为1MB。那么存储10000个参数需要的内存大小为10000x4 Bytes,约为39KB。存储100万个参数需要的内存大小为39x100/......

叶子的博客 1万+

LightTools中VBA宏的编写入门

LightTools和VBA联动

bestgamer的博客 2348

【笔记】深度学习模型训练的 GPU 内存优化之旅③:内存交换篇

梳理并分享与内存交换技术相关的高水平论文。

weixin_43254181的博客 1395

手把手教你用二茂铁催化剂搞定醇的动力学拆分(保姆级实验避坑指南)

本文详细介绍了使用平面手性二茂铁催化剂进行醇的动力学拆分的全流程,包括催化剂选择与制备、反应体系搭建与条件优化、实时监测与反应淬灭、产物分离与纯化等关键步骤。通过实战案例和避坑指南,帮助实验人员实现>98% ee的拆分效果,特别适合需要高光学纯度二级芳基醇或烯丙醇的研究者。

weixin_30500105的博客 438

SpringBoot+Flowable 6.8.0实战:5分钟搞定免登录流程图设计器

本文详细介绍了如何通过SpringBoot与Flowable 6.8.0深度整合,快速实现免登录流程图设计器的集成方案。通过排除默认安全配置、自定义安全策略和用户模拟服务,开发者可在5分钟内完成设计器的部署,适用于快速原型开发和企业内部工具搭建。

weixin_29204205的博客 280

如何计算一个深度学习模型中的参数量、运算量,占用内存,占用显存

提示:以下是本篇文章正文内容,下面案例可供参考。

xmu_cjs的博客 861

STM32F103四位数码管动态显示实战:从硬件连接到代码调试(附Proteus仿真)

本文详细介绍了STM32F103驱动四位数码管的动态显示技术,从硬件连接到代码调试的全过程。内容包括共阴/共阳数码管的区别、GPIO配置、动态显示原理及优化方法,并附有Proteus仿真验证。通过实战案例,帮助开发者快速掌握STM32数码管动态显示的核心技术。

weixin_29168393的博客 470

我的模型有多快?——深度学习网络模型的运算复杂度、空间占用和内存访问情况计算

前段时间看了几个笔试题,涉及 DNN 的模型复杂度,主要是参数量和计算复杂度的问题。当时搜了一下感觉中文网上的内容比较乱。刚好本文是对神经网络模型资源消耗情况的一篇介绍,就不自己写了,把关键内容做了一下编译。 原文见 http://machinethink.net/blog/how-fast-is-my-model/ 。 深度网络的计算消耗是学术 paper 相对少见的话题。当然,早期网络精度...

莉莉兹的摸鱼日记 3万+

ESP32天线阵列实现Wi-Fi空间成像与无直视定位

Wi-Fi信道状态信息(CSI)是OFDM系统中表征多径传播特性的基础物理层参数,其复数值包含幅度与相位,可反映无线环境的空间特征。基于CSI的射频感知技术,通过提取子载波级信道响应,结合阵列信号处理,实现到达角(AoA)估计与深度映射,本质是将通信链路重构为空间域传感器。该技术无需专用雷达硬件,具备低成本、被动式、隐私友好等工程优势,在室内定位、行为识别、仓储导航等场景具有广泛落地价值。本文聚焦ESP32平台,详解多芯片相位同步、CSI零拷贝采集、嵌入式MUSIC算法及信道图谱轻量化部署等关键实现。

weixin_30632267的博客 237

【知识图谱】neo4j桌面版安装与配置-解决无法启功问题(2025年最新最全教程)

(经历过各种版本NEO4J,相比社区版而言,个人感觉桌面版更适合新手,安装调试更少更方便。如果是社区版改桌面版的,记得删除系统变量里NEO4J_HOME这个变量,否则会报错。

知识靠谱的博客 2万+

【深度学习实战(48)】如何计算模型的参数量、占用内存、CPU、GPU占用的算力

【深度学习实战(48)】如何计算模型的参数量、占用内存、CPU、GPU占用的算力

m0_51579041的博客 2598

Android12+RK3588 多应用录音适配

两个应用能够同时录音,在Android12上的实现

guanmingyuangmy的博客 2226

Java内存模型

在多核时代,如何提高CPU的性能成为了一个永恒的话题,而这个话题的讨论主要就是如何定义一个高性能的内存模型,内存模型用于定义处理器的各层缓存与共享内存的同步机制及线程和内存交互的规则。 Java的世界也有属于它自己的内存模型,Java内存模型,即Java Memory Model,简称JMM。由于Java被定义成一种跨平台的语言,所以在内存的描述上面也要能是跨平台的,Java虚拟机试图定义一种统一的

seaboat——a free boat on the sea.(公众号:远洋号) 2776

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

浅谈JAVA中JVM内存模型(1)

概念: List item

qq_43265564的博客 214

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

java语言怎么解释,使用/教程/实例

学好java语言到底能做什么呢?学好java语言到底能做什么呢?1.可以自己设计游戏与其玩游戏,不如自己设计游戏;或许你不知道,在以前,我们玩的很多手机游戏都是通过Java开 他们运用的就是Java 。Java做安卓不单单是指系统,还有APP,对于更多的开发人员来说,他们更多的时间是花在开发APP上面。 搞Java怎么玩深度学习,生产环境用DL4J啊不过大众编程语言特别是面向生产环境的语言并不是只有Python的,作为多年来盘踞生产环境的扛把子Java语言,生态同样丰富得吓人。所以,如果用Java,怎

facai122的博客 233

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

并发编程JUC深度学习(六)内存模型_2

Happens-Before

左灯右行的爱情 269

java 线程缺陷_Java 线程/内存模型的缺陷和增强

shyguy原创Java在语言层次上实现了对线程的支持。它提供了Thread/Runnable/ThreadGroup等一系列封装的类和接口,让程序员可以高效的开发Java多线程应用。为了实现同步,Java提供了synchronize关键字以及object的wait()/notify()机制,可是在简单易用的背后,应藏着更为复杂的玄机,很多问题就是由此而起。一、Java内存模型在了解Java的同步...

weixin_35275671的博客 197

并发编程JUC深度学习(六)内存模型_1

内存模型_1

左灯右行的爱情 269

【八股消消乐】你了解JVM内存模型吗?

😊你好,我是小航,一个正在变秃、变强的文艺倾年。🔔本专栏《八股消消乐》旨在记录个人所背的八股文,包括等相关知识点,期待与你一同探索、学习、进步,一起卷起来叭!

文艺倾年的博客 1044

Java开发者!终于找到一个看得懂的JVM内存模型了,小白也能看明白

一、概述 本文主要来分析JMM内存模型,英文名JAVA Memory Model,它是与计算机硬件有关的一个概念。为了保证共享内存的正确性(可见性、有序性、原子性),内存模型定义了共享内存系统中多线程程序读写操作行为的规范。 Java代码是怎么运行的? Java的基本类型 Java虚拟机是如何加载Java类的 JVM是如何执行方法调用的?(上) JVM是如何执行方法调用的?(下) JVM是如何处理异常的? JVM是如何实现反射的? JVM是怎么实现invokedynamic的?(上) JVM

212
上一篇: Channel最佳实践之基本规则【译】
下一篇: 依赖注入不是Java的专利,Golang也有
codehole_
博客等级 码龄7年 34粉丝 132原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值