原文:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html 第一章 译者:方腾飞

在多核系统中,处理器一般有一层或者多层的缓存,这些的缓存通过加速数据访问(因为数据距离处理器更近)和降低共享内存在总线上的通讯(因为本地缓存能够满足许多内存操作)来提高CPU性能。缓存能够大大提升性能,但是它们也带来了许多挑战。例如,当两个CPU同时检查相同的内存地址时会发生什么?在什么样的条件下它们会看到相同的值?

在处理器层面上,内存模型定义了一个充要条件,“让当前的处理器可以看到其他处理器写入到内存的数据”以及“其他处理器可以看到当前处理器写入到内存的数据”。有些处理器有很强的内存模型(strong memory model),能够让所有的处理器在任何时候任何指定的内存地址上都可以看到完全相同的值。而另外一些处理器则有较弱的内存模型(weaker memory model),在这种处理器中,必须使用内存屏障(一种特殊的指令)来刷新本地处理器缓存并使本地处理器缓存无效,目的是为了让当前处理器能够看到其他处理器的写操作或者让其他处理器能看到当前处理器的写操作。这些内存屏障通常在lock和unlock操作的时候完成。内存屏障在高级语言中对程序员是不可见的。

在强内存模型下,有时候编写程序可能会更容易,因为减少了对内存屏障的依赖。但是即使在一些最强的内存模型下,内存屏障仍然是必须的。设置内存屏障往往与我们的直觉并不一致。近来处理器设计的趋势更倾向于弱的内存模型,因为弱内存模型削弱了缓存一致性,所以在多处理器平台和更大容量的内存下可以实现更好的可伸缩性

“一个线程的写操作对其他线程可见”这个问题是因为编译器对代码进行重排序导致的。例如,只要代码移动不会改变程序的语义,当编译器认为程序中移动一个写操作到后面会更有效的时候,编译器就会对代码进行移动。如果编译器推迟执行一个操作,其他线程可能在这个操作执行完之前都不会看到该操作的结果,这反映了缓存的影响。

 

此外,写入内存的操作能够被移动到程序里更前的时候。在这种情况下,其他的线程在程序中可能看到一个比它实际发生更早的写操作。所有的这些灵活性的设计是为了通过给编译器,运行时或硬件灵活性使其能在最佳顺序的情况下来执行操作。在内存模型的限定之内,我们能够获取到更高的性能。

看下面代码展示的一个简单例子:

01 ClassReordering {
02  
03 int x = 0, y = 0;
04  
05 public void writer() {
06  
07 x = 1;
08  
09 y = 2;
10  
11 }
12  
13 public void reader() {
14  
15 int r1 = y;
16  
17 int r2 = x;
18  
19 }
20  
21 }

让我们看在两个并发线程中执行这段代码,读取Y变量将会得到2这个值。因为这个写入比写到X变量更晚一些,程序员可能认为读取X变量将肯定会得到1。但是,写入操作可能被重排序过。如果重排序发生了,那么,就能发生对Y变量的写入操作,读取两个变量的操作紧随其后,而且写入到X这个操作能发生。程序的结果可能是r1变量的值是2,但是r2变量的值为0。

Java内存模型描述了在多线程代码中哪些行为是合法的,以及线程如何通过内存进行交互。它描述了“程序中的变量“ 和 ”从内存或者寄存器获取或存储它们的底层细节”之间的关系。Java内存模型通过使用各种各样的硬件和编译器的优化来正确实现以上事情。

 

Java包含了几个语言级别的关键字,包括:volatile, final以及synchronized,目的是为了帮助程序员向编译器描述一个程序的并发需求。Java内存模型定义了volatile和synchronized的行为,更重要的是保证了同步的java程序在所有的处理器架构下面都能正确的运行。

Java内存模型FAQ(一) 什么是内存模型的更多相关文章

  1. Java基础知识强化100:JVM 内存模型

    一. JVM内存模型总体架构图:  方法区和堆由所有线程共享,其他区域都是线程私有的 二. JVM内存模型的结构分析: 1. 类装载器(classLoader) 类装载器,它是在java虚拟机中用途是 ...

  2. Java内存管理-JVM内存模型以及JDK7和JDK8内存模型对比总结(三)

    勿在流沙住高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 上一篇分享了JVM及其启动流程,今天介绍一下JVM内部的一些区域,以及具体的区域在运行 ...

  3. Java虚拟机(二):JVM内存模型

    所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢?OutOfMemoryError的异常到底涉及到运行时数据的哪块区域?该怎么解决呢?其实如果你经常解决服务器性能问题,那么这些问 ...

  4. Java入门系列(五)JVM内存模型

    概述 根据<Java 虚拟机规范>中的说法,Java 虚拟机的内存结构可以分为公有和私有两部分. 公有指的是所有线程都共享的部分,指的是 Java 堆.方法区.常量池. 私有指的是每个线程 ...

  5. JVM内存模型、指令重排、内存屏障概念解析

    在高并发模型中,无是面对物理机SMP系统模型,还是面对像JVM的虚拟机多线程并发内存模型,指令重排(编译器.运行时)和内存屏障都是非常重要的概念,因此,搞清楚这些概念和原理很重要.否则,你很难搞清楚哪 ...

  6. java语言:Linux与JVM的内存关系分

    在一些物理内存为8g的服务器上,主要运行一个Java服务,系统内存分配如下:Java服务的JVM堆大小设置为6g,一个监控进程占用大约 600m,Linux自身使用大约800m.从表面上,物理内存应该 ...

  7. JAVA常见错误处理方法 和 JVM内存结构

    OutOfMemoryError在开发过程中是司空见惯的,遇到这个错误,新手程序员都知道从两个方面入手来解决:一是排查程序是否有BUG导致内存泄漏:二是调整JVM启动参数增大内存.OutOfMemor ...

  8. (翻译)什么是Java的永久代(PermGen)内存泄漏

    http://www.codelast.com/?p=7248 转载请注明出处:http://www.codelast.com/ 本文是我对这篇文章的翻译:What is a PermGen leak ...

  9. 从Java虚拟机的内存区域、垃圾收集器及内存分配原则谈Java的内存回收机制

    一.引言: 在Java中我们只需要轻轻地new一下,就可以为实例化一个类,并分配对应的内存空间,而后似乎我们也可以不用去管它,Java自带垃圾回收器,到了对象死亡的时候垃圾回收器就会将死亡对象的内存回 ...

  10. 转:JAVA常见错误处理方法 和 JVM内存结构

    OutOfMemoryError在开发过程中是司空见惯的,遇到这个错误,新手程序员都知道从两个方面入手来解决:一是排查程序是否有BUG导致内存泄漏:二是调整JVM启动参数增大内存.OutOfMemor ...

随机推荐

  1. (12)C#枚举,结构

    枚举 枚举类型是类似自定义的一个类,类里放着你自己定义的常量,关键字enum. enum Season{spring,summer,fall,winter} 想用这里的常量的话,首先把变量定义成 Se ...

  2. java的IO,AIO简单对比

    以下内容转载lzzzl Channel 通道 Buffer 缓冲区 Selector 选择器 其中Channel对应以前的流,Buffer不是什么新东西,Selector是因为nio可以使用异步的非堵 ...

  3. HKSCS

    香港增补字符集(HKSCS) 背景介绍 背景资料 ======== 目前,大部份不同語文的電腦系統,都有不同的編碼標準.如中文的系統就有BIG5和GB2312/GBK.各種文字有不同的文字編碼,不同系 ...

  4. JAVA中使用freemark生成自定义文件(json、excel、yaml、txt)

    原文:http://blog.csdn.net/jinzhencs/article/details/51461776 场景:在我们工作中,有时需要生成一些文件,可能它不是一种标准的格式,比如JSON. ...

  5. python的模块itsdangerous

    这个模块主要用来签名和序列化 使用场景: 一.给字符串添加签名: 发送方和接收方拥有相同的密钥--"secret-key",发送方使用密钥对发送内容进行签名,接收方使用相同的密钥对 ...

  6. 鸟哥的linux私房菜学习记录之计算机概论

  7. ES6里关于数字的拓展

    一.指数运算符 ES6引入的唯一一个JS语法变化是求幂运算符,它是一种将指数应用于基数的数学运算.JS已有的Math.pow()方法可以执行求幂运算,但它也是为数不多的需要通过方法而不是正式的运算符来 ...

  8. ElasticSearch测试数据

    curl命令数据 curl -XPUT http://127.0.0.1:9200/us/user/1 -d "{\"email\":\"john@smith. ...

  9. Python-使用Magellan进行数据匹配总结

    参考:http://www.biggorilla.org/zh-hans/walkt/ 使用Magellan进行数据匹配过程如下: 假设有两个数据源为A和B, A共有四列数据:(A_Column1,A ...

  10. 【Zookeeper】Zookeeper部署笔记

    Zookeeper部署笔记 .上传zk安装包 .解压 .配置(先在一台节点上配置) .1添加一个zoo.cfg配置文件 $ZOOKEEPER/conf mv zoo_sample.cfg zoo.cf ...