学过JAVA的人都知道,程序运行过程中的临时数据,都是从外部存储设备调入内存(物理内存)中,再进行读写操作的。而计算机在执行程序时,对程序的每条指令都是在CPU中执行的,而指令的执行,势必涉及到对数据的读写操作。

  于是就产生了这样一个问题,CPU指令的执行速度是很快的,但是从内存中读取和写入数据的速度却是比较慢的。如果对数据的任何操作,都需要CPU和内存打交道,而由于内存的读取速度远远慢于CPU的执行速度,这样就大大降低了CPU执行的效率,于是就有了CPU高速缓存的概念。

  CPU,CPU高速缓存,内存协同工作过程

  1、程序运行过程,会将所需要操作的业务数据加载到内存中,并复制一份到CPU的高速缓存中。

  2、CPU指令执行时,直接从CPU高速缓存中读取和写入数据,提高工作效率。

  3、CPU运算结束后,将结果写入CPU高速缓存,此时再同步至内存中。

  

  多线程场景下a = a + 1的难题

  程序执行该代码时,JVM进程中首先开启一个线程,从外部存储设备中加载class文件至内存中并赋予了a初始值,并将a值复制一份存储至CPU高速缓存中。运算时,CPU指令首先从高速缓存中读取a值,进行+1操作后将结果写入高速缓存中,再由高速缓存同步至内存中,于是一个加法运算的全过程就顺利完成了。

  这个代码在单线程的场景中,是没有任何问题的。但如果是运行在多核CPU的多线程场景下就会出问题了。

  在多核CPU下,每个线程都可能拥有自己独立的CPU,每个线程运行时都有自己的CPU高速缓存,这样就容易造成计算结果的脏数据。

  假设a在JVM加载初始化过程被赋值为0,线程A和B同时执行a = a + 1的操作,此时我们预期的结果可能都是a最终的结果为2。

  但是,如果线程A,B同时从内存中复制了a值至各自的CPU高速缓存中,A执行完了a = 1写入自己线程的缓存,再同步回内存,B也如此。这样一来,最终a的值就定格在了1,这是和预期结果所相悖的。也就是说,在多CPU,多线程编程的场景下,很有可能存在计算结果为脏数据的现象。

  为解决该难题,就需要使用volatile关键字对变量进行修饰了,至于volatile关键字为啥有此神奇功效,请看本博客的《深入剖析volatile关键字》。

  

a=a+1背后的内存模型和CPU高速缓存的更多相关文章

  1. 黑马-----内存模型和volatile详解

    黑马程序员:Java培训.Android培训.iOS培训..Net培训 JAVA线程-内存模型和volatile详解 一.单核内存模型 1.程序运行时,将临时数据存放到Cache中 2.将CPU计算所 ...

  2. Java内存模型和JVM内存管理

    Java内存模型和JVM内存管理   一.Java内存模型: 1.主内存和工作内存(即是本地内存): Java内存模型的主要目标是定义程序中各个变量的访问规则,即在JVM中将变量存储到内存和从内存中取 ...

  3. 【Java】JMM内存模型和JVM内存结构

    JMM内存模型和JVM内存结构 JAVA内存模型(Java Memory Model) Java内存模型,一般指的是JDK 5 开始使用的新的内存模型,主要由JSR-133: JavaTM Memor ...

  4. Java 内存模型和 JVM 内存结构真不是一回事

    这两个概念估计有不少人会混淆,它们都可以说是 JVM 规范的一部分,但真不是一回事!它们描述和解决的是不同问题,简单来说, Java 内存模型,描述的是多线程允许的行为 JVM 内存结构,描述的是线程 ...

  5. 并发一:Java内存模型和Volatile

    并发一:Java内存模型和Volatile 一.Java内存模型(JMM) Java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和在内存中取出变量的底层细节,是围绕着 ...

  6. JVM内存结构、Java内存模型和Java对象模型

    Java作为一种面向对象的,跨平台语言,其对象.内存等一直是比较难的知识点.而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚.比如本文要讨论的JVM内存结构.Java内存模型和Java对象模型 ...

  7. JAVA内存模型和Happens-Before规则

    前言 上一篇文章王子给大家介绍了并发编程中比较关心的三个核心问题,可见性.有序性和原子性. 今天我们继续来探索并发编程的内容,聊一聊JAVA的内存模型和Happens-Before规则. JAVA内存 ...

  8. 基于JVM原理、JMM模型和CPU缓存模型深入理解Java并发编程

    许多以Java多线程开发为主题的技术书籍,都会把对Java虚拟机和Java内存模型的讲解,作为讲授Java并发编程开发的主要内容,有的还深入到计算机系统的内存.CPU.缓存等予以说明.实际上,在实际的 ...

  9. Java线程角度的内存模型和volatile型变量

    内存模型的目标是定义程序中各个变量的访问 规则,即在虚拟机中将变量(包括实例字段,静态字段和构成数组对象的元素,不包括局部变量与方法参数,因为后者是线程私有的)存储到内存和从内存中取出变量这样的底层细 ...

随机推荐

  1. C++ c++与C语言的区别(三目运算符,const修饰符)

    //区别⑦:三目运算符(C++版本) #include<iostream> using namespace std; //三目运算符 C语言返回变量的值 C++语言是返回变量本身 void ...

  2. dedecms中如何去掉文章页面的广告

    在arcticle_arcticle.htm页面找到广告调用代码{dede:myad name='myad'/}全部去掉就好了,如果要换成自己的广告,就换广告位标识 myad 就可以了

  3. php -- 判断文件是否存在

    file_exists is_file is_dir 基本上,PHP的 file_exists = is_dir + is_file 写程序验证一下: 分别执行1000次,记录所需时间. ------ ...

  4. 【cf492】D. Vanya and Computer Game(二分)

    http://codeforces.com/contest/492/problem/D 有时候感觉人sb还是sb,为什么题目都看不清楚? x per second, y per second... 于 ...

  5. PHP时间戳 strtotime()使用方法和技巧

    在php中我想要获取时间戳有多种方法,最常用的就是使用time函数与strtotime()函数把日期转换成时间戳了, 下面我来给大家分享一下时间戳函数 strtotime用法. 获取指定的年月日转化为 ...

  6. ActiveMQ搭建

    下载 到ActiveMQ官网,找到下载点. 目前, 官网为http://activemq.apache.org/ Linux版本下载点之一为:http://apache.fayea.com/activ ...

  7. Spark源代码阅读笔记之MetadataCleaner

    MetadataCleaner执行定时任务周期性的清理元数据(metadata),有6种类型的元数据:MAP_OUTPUT_TRACKER.executor跟踪各个map任务输出的存储位置的数据,依据 ...

  8. 主线程不能执行耗时的操作,子线程不能更新Ui

    在Android项目中经常有碰到这样的问题,在子线程中完成耗时操作之后要更新UI,下面就自己经历的一些项目总结一下更新的方法: 在看方法之前看一下Android中消息机制: 引用 Message:消息 ...

  9. php 实现Iterator 接口

    <?php class MyIterator implements Iterator{ private $var = array(); public function __construct($ ...

  10. Delphi XE5通过WebService开发Web服务端和手机客户端

    Delphi XE5通过WebService开发Web服务端和手机客户端介绍 我们开发一个三层的android程序 建立一个webservices  stand-alone vcl applicati ...