展开

关键词

Java模型与指令

本文暂不讲JMM(Java Memory Model)中的主, 工作以及数据如何在其中流转等等,这些本身还牵扯到硬件架构, 直接上手容易绕晕, 先从以下几个点探索JMM原子性有序性可见性指令排 编译器优化主要是Java虚拟机层面的可见性, 下文会有详细讲述.指令排指令排是指在程序执行过程中, 为了性能考虑, 编译器和CPU可能会对指令新排序.CPU指令排一条汇编指令的执行是可以分为很多步骤的 举个例子 A = B + C, 需要如下指令指令1 : 加载B到寄器R1中指令2 : 加载C到寄器R2中指令3 : 将R1与R2相加, 得到R3指令4 : 将R3赋值给A意下图红色框选部分, 指令 1, 2独立执行, 互不干扰.指令3依赖于指令1, 2加载结果, 因此红色框选部分表示在等待指令1, 2结束.待指令1, 2都已经走完MEM部分, 数据加载到后, 指令3继续执行计算EX.同理指令4 解决方案也很简单, 只要给stop加上volatile关键字, 再次打印汇编代码, 发现他每次都会检查stop的值.就不会出现无限循环了.再来看两个从Java语言规范中摘取的例子, 也是涉及到编译器优化

86050

【死磕Java并发】—–Java模型之排序

意as-if-serial只保证单线程环境,多线程环境下无效。 但是,不是说通过排序,B可能会排在A之前执行么,为何还会在A happens-beforeB呢? 其实JVM对异常做了一种特殊的处理,为了保证as-if-serial语义,Java异常处理机制对排序做了一种特殊的处理:JIT在排序时会在catch语句中插入错误代偿代码(a = 3),这样做虽然会导致 答案是不一定(:X86CPU不支持写写排序,如果是在x86上面操作,这个一定会是a=1,LZ搞了好久都没有测试出来,最后查资料才发现)。 参考资料周志明 :《深入理解Java虚拟机》方腾飞:《Java并发编程的艺术》

33460
  • 广告
    关闭

    腾讯云前端性能优化大赛

    首屏耗时优化比拼,赢千元大奖

  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    【死磕Java并发】—– Java模型之排序

    意as-if-serial只保证单线程环境,多线程环境下无效。 但是,不是说通过排序,B可能会排在A之前执行么,为何还会在A happens-beforeB呢? 其实JVM对异常做了一种特殊的处理,为了保证as-if-serial语义,Java异常处理机制对排序做了一种特殊的处理:JIT在排序时会在catch语句中插入错误代偿代码(a = 3),这样做虽然会导致 答案是不一定(:X86CPU不支持写写排序,如果是在x86上面操作,这个一定会是a=1,LZ搞了好久都没有测试出来,最后查资料才发现)。 参考资料周志明 :《深入理解Java虚拟机》方腾飞:《Java并发编程的艺术》

    43770

    【死磕Java并发】-----Java模型之排序

    意as-if-serial只保证单线程环境,多线程环境下无效。 但是,不是说通过排序,B可能会排在A之前执行么,为何还会在A happens-beforeB呢? 其实JVM对异常做了一种特殊的处理,为了保证as-if-serial语义,Java异常处理机制对排序做了一种特殊的处理:JIT在排序时会在catch语句中插入错误代偿代码(a = 3),这样做虽然会导致 答案是不一定(:X86CPU不支持写写排序,如果是在x86上面操作,这个一定会是a=1,LZ搞了好久都没有测试出来,最后查资料才发现)。 参考资料周志明 :《深入理解Java虚拟机》方腾飞:《Java并发编程的艺术》END

    29420

    Java与堆外

    一般情况下,Java 中分配的非空对象都是由 Java 虚拟机的垃圾收集器管理的,也称为堆(on-heap memory)。 彻底回收时,垃圾收集器会对所有分配的堆进行完整的扫描,这意味着一个要的事实——这样一次垃圾收集对 Java 应用造成的影响,跟堆的大小是成正比的。过大的堆会影响 Java 应用的性能。 但是 Java 本身也在不断对堆的实现方式做改进。两者各有什么优缺点? 第一类是生命周期较短,且结构简单的对象,在池中复利用这些对象能增加CPU缓的命中率,从而提高性能。第二种情况是加载含有大量复对象的大片数据,此时使用池能减少垃圾回收的时间。 堆外有以下特点:对于大有良好的伸缩性对垃圾回收停顿的改善可以明显感觉到在进程间可以共享,减少虚拟机间的复制Lawery还提到堆外要的还不是它能改进性能,而是它的确定性。

    1.6K40

    新认识 Java 中的映射(mmap)

    区分他们也很简单,例如 FileWriter,FileReader 在于 java.io 包中,他们属于普通 IO;FileChannel 在于 java.nio 包中,也是 Java 最常用的文件操作类 但这不是这一节的点,大家有没有想过,pageCache 其实本身也是一层缓冲,实际写入 1byte 并不是同步刷盘的,相当于写入了,pageCache 刷盘由操作系统自己决策。 主要就在于 filechannel 的 readwrite 底层相关联的系统调用,是需要切换核态和用户态的,意,这里跟拷贝没有任何关系,导致态切换的根本原因是 readwrite 关联的系统调用本身 ,意,这里跟拷贝还是没有任何关系,导致态不发生切换的根本原因是 mmap 关联的系统调用本身。 ,导致 cpu 的不堪负(但这样承担起动态映射与异步回收的开销)。

    6920

    Java-一个Java对象到底占多少

    分配是做优化的基础,如果不了解Java分配的知识,可能会带偏我们优化的方向。 所以这篇文章我们以“一个对象占多少”为引子来谈谈Java分配。 指针的长度是固定的,不去说它了,点看它所指向的对象在中占多少。 这种类型的Object的 Markword 一共是8个字节(64位),其中25位暂时没有使用,31位储对象的hash值(意这里储的hash值对根据对象地址算出来的hash值,不是写hashcode Java中基本数据类型和引用类型的分配知识,点分析了引用类型的对象头,并介绍了JOL工具的使用延伸到Android平台,介绍了一种获取Android中对象的对象头信息的方法,并对比了ART和Hotspot

    40320

    深入理解Java模型(二)——排序

    意,这里所说的数据依赖性仅针对单个处理器中执行的指令序列和单个线程中执行的操作,不同处理器之间和不同线程之间的数据依赖性不被编译器和处理器考虑。 为了遵守as-if-serial语义,编译器和处理器不会对在数据依赖关系的操作做排序,因为这种排序会改变执行结果。但是,如果操作之间不在数据依赖关系,这些操作可能被编译器和处理器排序。 as-if-serial语义使单线程程序员无需担心排序会干扰他们,也无需担心可见性问题。 此时,变量a还根本没有被线程A写入,在这里多线程程序的语义被排序破坏了!※:本文统一用红色的虚箭线表示错误的读操作,用绿色的虚箭线表示正确的读操作。 在单线程程序中,对在控制依赖的操作排序,不会改变执行结果(这也是as-if-serial语义允许对在控制依赖的操作做排序的原因);但在多线程程序中,对在控制依赖的操作排序,可能会改变程序的执行结果

    43040

    Java管理(一、分配)

    关于Java分配,很多问题都模模糊糊,不能全面贯通理解。 今查阅资料,欲求深入挖掘,彻底理清java分配脉络,只因水平有限,没达到预期效果,仅以此文对所研究到之处作以记录,为以后学习提供参考,避免头再来。 一、Java分配1、 Java有几种储区域? 3、Java模型* Java虚拟机将其管辖的大致分三个逻辑部分:方法区(Method Area)、Java栈和Java堆。     Java对象的总是在heap中分配。4、Java分配实例解析 常量池(constant pool)指的是在编译期被确定,并被保在已编译的.class文件中的一些数据。

    1.8K30

    四区,malloc,操作意事项

    四区? 小于4个字节,会放入寄器上malloc函数? 意:在堆区开辟的时候,就已经随机赋值了,因此可以用memset清空 ? 操作意事项1.不要返回局部变量的地址 vs编译器会先保留一次局部变量地址,防止程序员误操作 已经被释放,再操作属于非法行为 意返回地址用指针接收,与返回值用变量接收的区别:指针接收地址,相当于指针指向了的地址 2.不要操作已经释放的空间 不能再释放后*p=2000;再次操作释放的空间 ? 意其生命周期。3.不要复释放一块free释放的不是指针,而释放的指针指向的空间。free之后,如果指针又指向了另一块空间,可以直接使用该空间的数据。 而如果free之后指针没有指向其他空间,也没有指向NULL,依旧指向着已被释放的空间,所以操作数据会出错。一般在free之后都需要新指向新的空间或NULL ?

    15220

    Java学习笔记——管理Java管理

    Java管理简介Java虚拟机的管理分为以下几个运行时数据区:方法区堆虚拟机栈本地方法栈程序计数器其中,方法区和堆是所有线程共享的数据区,而其他的是线程隔离的数据区。 堆Java堆,又称GC堆,是GC的管理的主要区域。在虚拟机启动时创建。主要作用是放对象实例,几乎所有的对象实例都会放在Java堆中。Java堆可以处于物理不连续的空间中,只要逻辑连续即可。 通常Java堆是可扩展的。当Java堆无法申请到所需的空间来放实例,也无法扩展时,会抛出,OutOfMemoryError异常。 直接直接(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的区域,但是这部分也被频繁地使用,而且也可能导致OutOfMemoryError 异常出现 显然,本机直接的分配不会受到Java 堆大小的限制,但是,既然是,则肯定还是会受到本机总(包括RAM 及SWAP 区或者分页文件)的大小及处理器寻址空间的限制。

    21830

    Java溢出

    Java溢出堆溢出大量对象占据了堆空间,而且这些对象是强引用,导致无法回收直接溢出Java的NIO支持直接使用,从堆外获得空间,由于直接没有被Java虚拟机完全托管,若使用不当,容易触发直接溢出 多线程导致溢出线程的栈空间也是在堆外分配的,和直接相似,线程过多,会导致溢出。永久区溢出永久区是放元数据的区域。如果定义了太多类型,那么永久区有可能溢出。 GC效率低下引起溢出回收时,如果GC效率低下,那么系统的性能会收到严的影响。 如果系统堆空间太小,那么GC所占的时间就会较多,并且回收所释放的就会较少, 根据GC所占用的系统时间,以及释放的大小,虚拟机会评估GC的效率,一旦认为GC的效率过低,就会抛出溢出异常。 关于String的溢出java.lang.String主要由3部分组成:代表字符数组的Value、偏移量offset和长度count.

    27620

    Java管理

    溢出理论学习问题解决垃圾回收问题理论学习垃圾回收过程常用垃圾回收器工具篇GC日志命令行工具可视化工具问题解决溢出首先是比较”常见”的溢出,先解决两个小问题热热身: 1. Direct Memory直接:不在JVM中,Nio中的DirectByteBuffer对象通过引用Native堆中,避免Java堆和Native堆复制的方式来提升性能。 如果这部分加上Java大于服务器物理限制,也会导致JVM出现OOM。 :+PrintGCDetails下面具体gc日志还是比较好理解的,要关的有几点:-XX:+PrintHeapAtGC选项用于输出gc前后堆具体信息,可以看出本次gc回收eden区效果很明显。 使用抽样,结果也很抽象,占用比例最高的是byte[],而且查询并发上去之后,突增非常明显,有点诡异,因为我们的查询场景并不复杂,而且大部分情况下返回结果只有几十条。是不是什么地方泄露?

    87650

    Java模型

    Java的世界也有属于它自己的模型,Java模型,即Java Memory Model,简称JMM。 由于Java被定义成一种跨平台的语言,所以在的描述上面也要能是跨平台的,Java虚拟机试图定义一种统一的模型,能将各种底层硬件及操作系统的访问差异进行封装,使Java程序在不同硬件及操作系统上都能达到相同的并发效果 为更好理解JMM的工作机制,由图带入,从整体上看有几个比较要的主体,主、工作、变量、变量副本、线程等。 ,不同线程之间的工作是互相不可见的,且线程对变量的操作也只能是针对自己的工作;最后是关于线程之间的通信机制,由于线程之间不可直接传递,假如一条线程对一个变量进行新赋值,那么只能通过如下途径让另外一条线程知道 首先谈谈volatile,被此关键词声明的变量,每当有任何更改时都将立即同步到主中,而每个线程要使用这个变量时都要新从主刷新到工作,这样就确保了变量的可见性(当然,普通变量最终也会同步到主

    343100

    Java模型

    如果写好并发应用程序是服务端程序开发的难点之一,java语言和虚拟机提供了许多工具来帮助程序员降低门槛,并且各种中间件服务器、各类框架都努力的替程序员处理更多的并发希捷,使得程序员在编码过程中更关业务逻辑 一、硬件的模型和指令排序在讲解java虚拟机的模型之前,我们先了解一下硬件的模型和指令排序。 与处理器的乱序执行优化类似,Java虚拟机的即时编译器也有类似的指令排序(Instruction Reorder)优化。 意:此处的变量(Variables)与Java编程中所说的变量有所区别,它包括了实例字段、 静态字段和构成数组对象的元素,但不包括局部变量与方法参数,因为后者是线程私有的,不会在线程之间共享,不会有可见性问题 意,Java模型只要求上述两个操作必须按顺序执行,而没有保证是连续执行。

    36710

    Java模型

    Java虚拟机中定义了一种模型也就是JMM。目的是屏蔽各种硬件和操作系统的差异,以解决Java跨平台时能达到统一的访问效果。下面我们了解一下在JMM中是怎么划分的。 主与工作在JMM中有一个规定就是所有变量都必须储在主中。主也就是虚拟机的一部分区域。除此之外,每一个线程都有自己独立的工作。线程工作与主的区别是? 不同线程与线程间的是无法直接访问对方工作中的变量的。如果某一个线程需要访问其它线程工作中的变量时,它们只能通过主来完成。下图是线程与工作、主之间的关系图。? 上述所说的主和工作与并不是我们常说的虚拟机中的堆、 栈、 方法区等。它们并不是一个概念。为了方便理解我们可以认为主就是虚拟机堆中的储对象实例的,而工作就是虚拟机栈中的。 不允许一个变量从主读取了但工作不接受,或者从工作发起了同步但主不接受的情况。不允许变量在工作中改变了之后不同步到主中。

    21020

    Java区域

    正是因为 Java 程序员把控制权利交给 Java 虚拟机,一旦出现泄漏和溢出方面的问题,如果不了解虚拟机是怎样使用的,那么排查错误将会是一个非常艰巨的任务。 而 Java是否规整,取决于 GC 收集器的算法是”标记-清除”,还是”标记-整理”(也称作”标记-压缩”),值得意的是,复制算法也是规整的? 分配并发问题(补充容,需要掌握)在创建对象的时候有一个很要的问题,就是线程安全,因为在实际开发过程中,创建对象是很频繁的事情,作为虚拟机来说,必须要保证线程是安全的,通常来讲,虚拟机采用两种方式来保证线程安全 :CAS+失败试: CAS 是乐观锁的一种实现方式。 所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就试,直到成功为止。虚拟机采用 CAS 配上失败试的方式保证更新操作的原子性。

    31320

    Java区域

    Java虚拟机运行时数据区包含两类:由所有线程共享的数据区和线程隔离的数据区。线程共享的数据区包括方法区和堆。

    15130

    Java模型

    3)系统的排序:由于处理器使用缓和读写缓冲区,缓可能会改变写入变量提交到主中的次序,使得加载和储操作看上去是乱序执行。   屏障(Memory Barriers)  屏障是一种CPU指令,用于控制特定条件下的排序和可见性问题。   意此时是1和2是不能排序的,3和4同样不能排序。假设线程A先执行write方法,线程B后执行read方法,volatile的语义能保证线程B一定能看到线程A对count变量的更改。   其中2)和3)可以排序。意这并不违反单线程执行结果不改变的原则,假设4)为使用instance,只要保证2)和4)不做排序就能保证单线程执行结果不变。 参考资料  《Java访问排序的研究》https:tech.meituan.comjava-memory-reordering.html    《java并发编程的艺术》  《就是要你懂Java

    33541

    java分配

    中的局部变量随着方法的消失而消失。成员变量储在堆中的对象里面,由垃圾回收器负责回收。 意:栈里只有一个9 ,i1,i2,i3 都指向9 。 应用程序在运行中所创建的所有类实例或数组都放在这个堆中,并由应用所有的线程共享.跟CC++不同,Java中分配堆是自动初始化的。 Java中所有对象的储空间都是在堆中分配的,但是这个对象的引用却是在堆栈中分配,也就是说在建立一个对象时从两个地方都分配,在堆中分配的实际建立这个对象,而在堆栈中分配的只是一个指向这个堆对象的指针 堆是由垃圾回收来负责的,堆的优势是可以动态地分配大小,生期也不必事先告诉编译器,因为它是在运行时动态分配的,Java的垃圾收集器会自动收走这些不再使用的数据。 栈有一个很要的特殊性,就是在栈中的数据可以共享。

    49250

    相关产品

    • 云数据库 Memcached

      云数据库 Memcached

      腾讯云数据库 Memcached是腾讯自主研发的极高性能、内存级、持久化、分布式 Key-Value 存储服务。适用于高速缓存的场景,为您提供主从热备、自动容灾切换、数据备份、故障迁移、实例监控全套服务,无需您关注以上服务的底层细节......

    相关资讯

    热门标签

    活动推荐

      运营活动

      活动名称
      广告关闭

      扫码关注云+社区

      领取腾讯云代金券