JVM系列(三)[计算机硬件的内存模型,数据一致性问题,CPU指令乱序执行,合并写]

本文深入探讨了JVM内存模型与硬件内存的关系,阐述了存储器层次结构、数据一致性(总线锁、缓存锁、伪共享问题)以及CPU指令的乱序执行问题,通过内存屏障和JVM规范(JSR133)解释了如何保证顺序执行。此外,还介绍了合并写(WC)的概念及其在CPU性能优化中的作用。
摘要由CSDN通过智能技术生成

前言

JVM嘛,Java虚拟机,也就是一个虚拟的硬件机器,所以它的一切功能都是基于真实的硬件机器,可能做了一些灵活的应用.
所以学习JVM的内存模型前,需要先了解下计算机硬件是如何解决并发带来的数据一致性和乱序执行问题.
JVM的内存模型和计算机的内存模型是有一定的映射关系的,但很多定义并不相同.

内存模型

读取速度:CPU 远大于 内存 远大于 磁盘
这个远大于大概就是100倍+

存储器的层次结构

这个金字塔,从最上层L0开始,越往下 速度越慢,成本越低,空间越大
L0 L1 L2是CPU内部的缓存,每个CPU或者CPU的核心独享
在这里插入图片描述
在这里插入图片描述

数据一致性

上面看到L0 L1 L2是CPU内部的缓存
当两个CPU从L4或L3读取数据到自己的L2后,假如其中一个CPU修改了数据,就可能产生数据不一致的问题.
当然硬件的发明者不会这么傻,肯定有解决方案,那硬件是怎么保证数据一致性的呢?

总线锁

CPU去读主存或者其他层级的时候,是通过内存总线读的.
以前的CPU,为了保证数据一致性,会这么干:
CPU1访问变量t的时候,会锁住总线,这时候CPU2就不能访问变量t了,直到CPU1释放锁.

总线锁会锁住总线,使得其他CPU甚至不能访问内存中其他的地址,因而效率较低.

在这里插入图片描述

缓存锁+总线锁

各种缓存一致性协议
最常听的是intel的CPU的MESI协议,参考这个:https://www.cnblogs.com/z00377750/p/9180644.html
在这里插入图片描述

cache line 缓存行

cache line是读取缓存的基本单位

CPU去L3读取一个变量t时,假如t的数据很小,那么并不只是读取t自己,而是会带着t身边的一块数据,这个块成为"基本缓存单位",即cache line缓存行,大小一般是64Bits

伪共享问题

假如CPU1需要读写变量t1,CPU2需要读写变量t2,而t1和t2在同一个缓存行中,这俩CPU就会产生不必要的互相影响,不必要的重新读取变量
在这里插入图片描述
一些优秀的开源软件,代码中会规避掉缓存行的伪共享问题,比如Disruptor的cursor,就是前后各加了7个long变量,保证cursor变量一定是在独立的缓存行中,即缓存行对齐
下面我们来一对例子,验证一下伪共享:
反例:

    static void originalMethod() throws InterruptedException {
   
        long[] arr = new long[2];
        Thread t1 = new Thread(() -> {
   
            for (int i = 0; i < TIMES; i++) {
   
                arr[0] = i;
            }
        });
        Thread t2 = new Thread(() -> {
   
            for (int i = 0; i < TIMES; i++) {
   
                arr[1] = i;
            }
        });
        long start = System.currentTimeMillis();
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        long end = System.currentTimeMillis();
        System.out.println("originalMethod :" + (end - start));
    }

正例,就是多占一些内存,把使用的东西分成不同的缓存行:
这个实验结果,优化后快很多

	// 这个类,就是只用到了num,其他的参数用来填充缓存行
    static class Param {
   
        long l1, l2, l3, l4, l5, l6, l7;
        long num;
    }
    static void optimizedMethod() throws InterruptedException {
   
        Param[] arr = {
   new Param(), new Param()};
        Thread t1 = new Thread((
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值