ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Java 伪内存共享解决方案

2022-05-01 00:33:13  阅读:111  来源: 互联网

标签:缓存 Java 字节 填充 对象 解决方案 内存


简单的说一下伪内存共享是什么:

  cpu读取数据的顺序:cpu->寄存器->1级缓存->2级缓存->3级缓存(3级缓存开始是CPU共享的)->主内存->硬盘,读取数据不是一个对象或者一个字节为单位读取的,而已一缓存行为单位,CPU 不同缓存行的大小也不同,一般为32-256个字节,最常见的缓存行大小是64个字节。如果一个缓存行存了多个对象,两个cpu 分别都加载了其中的一个对象(  比如cpu1 加载 了A,cpu2 加载了B ),然后如果cpu1频繁的修改A,那么cpu2即便只是读取B对象,会因为cpu1修改了A对象,使A对象所在的缓存行失效,cpu2就需要频繁的从3级缓存中加载失效的缓存行。上面描述的不是必须竞争修改,cpu1,cpu2 没有同时修改同一份数据,这种不以必要但是又真是存在的缓存行失效问题叫做伪内存共享。

  

  

 

 

伪内存共享问题解决办法:

      填充缓存行,使整个Java对象占满整个缓存行。不同Java版本不一样,比如开启指针压缩的情况下,对象头标记8字节,对象类型指针4字节就是12 字节,如果我们只有一个long 类型的字段(8字节),然后Java对象是8字节对齐的,我们填充5个long 类型(40),这时候就是60字节,然后由padding 区域填满剩下的4字节。这样就占了整个缓存行。

 

  

 

      JDK7中填充空的属性部分版本会失效,这时候可以通过在父类中添加属性来填充。

 

 

     JDK8以后官方给出解决缓存行填充的注解@Contended,来使对象填充缓存行。但是默认情况加了也无效,需要 指定jvm 参数,使它生效需要同时开启 JVM 参数:-XX:-RestrictContended=false(这个参数的意思禁用Java类库以外的缓存行填充,这个参数默认是true),如果想Java自带类库缓存行填充都禁用 –XX: EnableContented=false就可以(默认是true)。

 

 

    另外在说说,缓存行填充不应该随意使用,除非你确定你需要它,测试,普通Java对象填充和不填充效果基本没区别(没区别是应为出现的概率比较小,并不是真的没区别),但是被volatile修饰的对象效率 差10倍,所以volatile的对象可能更加需要填充。volatile关键字也不应该乱用,用了它会大大的降低效率,除非你真的需要它带来的内存可见性和禁用指令重排序。

 

标签:缓存,Java,字节,填充,对象,解决方案,内存
来源: https://www.cnblogs.com/cxygg/p/16211958.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有