`
lingqi1818
  • 浏览: 249333 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

JMM的一些总结

阅读更多
懒得写,以下抄梁飞博客:http://javatar.iteye.com
JMM规范:

The rules for happens-before are:


Program order rule. Each action in a thread happens-before every action in that thread that comes later in the program order.



Monitor lock rule. An unlock on a monitor lock happens-before every subsequent lock on that same monitor lock.



Volatile variable rule. A write to a volatile field happens-before every subsequent read of that same field.



Thread start rule. A call to Thread.start on a thread happens-before every action in the started thread.



Thread termination rule. Any action in a thread happens-before any other thread detects that thread has terminated, either by successfully return from Thread.join or by Thread.isAlive returning false.



Interruption rule. A thread calling interrupt on another thread happens-before the interrupted thread detects the interrupt (either by having InterruptedException tHRown, or invoking isInterrupted or interrupted).



Finalizer rule. The end of a constructor for an object happens-before the start of the finalizer for that object.



Transitivity. If A happens-before B, and B happens-before C, then A happens-before C.



----------------------------


什么是happens-before?
happens-before就是“什么什么一定在什么什么之前运行”,也就是保证顺序性。
因为CPU是可以不按我们写代码的顺序执行内存的存取过程的,也就是指令会乱序或并行运行,
只有上面的happens-before所规定的情况下,才保证顺序性。
如:
Java代码
public class Test {  
 
    private int a = 0;  
 
    private long b = 0;  
 
    public void set() {  
        a = 1;  
        b = -1;  
    }  
 
    public void check() {  
        if (! ((b == 0) || (b == -1 && a == 1))  
            throw new Exception("check Error!");  
    }  


public class Test {

private int a = 0;

private long b = 0;

public void set() {
a = 1;
b = -1;
}

public void check() {
if (! ((b == 0) || (b == -1 && a == 1))
throw new Exception("check Error!");
}
}

对于set()方法的执行:
1. 编译器可以重新安排语句的执行顺序,这样b就可以在a之前赋值。如果方法是内嵌的(inline),编译器还可以把其它语句重新排序。
2. 处理器可以改变这些语句的机器指令的执行顺序,甚到同时执行这些语句。
3. 存储系统(由于被缓存控制单元控制)也可以重新安排对应存储单元的写操作顺序,这些写操作可能与其他计算和存储操作同时发生。
4. 编译器,处理器和存储系统都可以把这两条语句的机器指令交叉执行。
例如:在一台32位的机器上,可以先写b的高位,然后写a,最后写b的低位,(注:b为long类型,在32位的机器上分高低位存储)
5. 编译器,处理器和存储系统都可以使对应于变量的存储单元一直保留着原来的值,
以某种方式维护相应的值(例如,在CPU的寄存器中)以保证代码正常运行,直到下一个check调用才更新。
...
在单线程(或同步)的情况下,上面的check()永远不会报错,
但非同步多线程运行时却很有可能。


并且,多个CPU之间的缓存也不保证实时同步,
也就是说你刚给一个变量赋值,另一个线程立即获取它的值,可能拿到的却是旧值(或null),
因为两个线程在不同的CPU执行,它们看到的缓存值不一样,
只有在synchronized或volatile或final的性况下才能保证正确性,
很多人用synchronized时只记得有lock的功能,而忘记了线程间的可见性问题。
如:
Java代码
public class Test {  
 
    private int n;  
 
    public void set(int n) {  
        this.n = n;  
    }  
 
    public void check() {  
        if (n != n)  
            throw new Exception("check Error!");  
    }  


public class Test {

    private int n;

    public void set(int n) {
        this.n = n;
    }

    public void check() {
        if (n != n)
            throw new Exception("check Error!");
    }
}

check()中的 n != n 好像永远不会成立,因为他们指向同一个值,但非同步时却很有可能发生。

另外,JMM不保证创建过程的原子性,读写并发时,可能看到不完整的对象,
这也是为什么单例模式中著名的"双重检查成例"方法,在Java中行不通。(但.Net的内存模型保证这一点)
分享到:
评论

相关推荐

    深入理解java内存模型

    本书目录 基础 并发编程模型的分类 Java内存模型的抽象 ...总结 处理器内存模型 JMM,处理器内存模型与顺序一致性内存模型之间的关系 JMM的设计 JMM的内存可见性保证 JSR-133对旧内存模型的修补 个人简介 参考文献

    Java重要的基础知识/高级特性/工作经验170页笔记

    精心制作的170页Java学习笔记 这本笔记要讨论的主题...我对这本笔记的期待是,帮助所有想要了解上面这些topic的人能有个比较能够快速参考的资源,因为这本笔记是我整理了一些我认为不错的文章/书籍/原始码之后的成果.

    jvm详细内存模型图1

    查看《深入理解Java虚拟机》后,自己简单总结的jvm相关的简单模型图。

    深入理解Java内存模型??总结

    JMM和处理器内存模型在设计时会对顺序一致性模型做一些放松,因为如果完全按照顺序一致性模型来实现处理器和JMM,那么很多的处理器和编译器优化都要被禁止,这对执行性能将会有很大的影响。  根据对不同类型读/写...

    深入理解Java内存模型.程晓明(带书签文字版).pdf

    基础 4 ...总结 66 处理器内存模型 66 JMM,处理器内存模型与顺序一致性内存模型之间的关系 68 JMM 的设计 69 JMM 的内存可见性保证 72 JSR-133 对旧内存模型的修补 73 个人简介 74 参考文献 74

    JVM面试复习.pdf

    JVM基础知识点讲解总结 包括JVM的内存结构、Java线程间通信、JMM底层原理、垃圾回收机制与双亲委派机制等等

    Java内存模型总结(上)

     Java线程之间的通信由Java内存模型(JMM)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见。  从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main ...

    java8源码-concurrency:java并发总结

    java8 源码 Java 并发多线程从简到全 参考: 目录: [TOC] 相关文档: kwseeker/netty Executors线程池.md 1 基本概念 1.1 ...由于不知道什么时候线程执行完毕并返回结果,主线程只能主动轮询查看线程

    Potato:阅读适用于Android采访的他妈的源代码-android source code

    [目录] 阅读面试的源代码计划 本项目逐步面试准备过程的...:JVM内存结构,Java内存模型(JMM),Java对象模型 :HashMap源码分析 :Java线程和并发知识总结 : 和并发结合总结 :java各种锁 安卓 交互:Android nati

    java8源码-highconcurrency:《实战Java高并发程序设计》葛一鸣、郭超着电子工业出版社2015年11月第一版书上部分代码

    这里也给大家做一个导读,我读完一章后会对每一章做出一些总结: 我认为这本书是从Java多线程的基础迈向实际开发架构的指导 第一章走入并行世界: 介绍了并发的基础理论:同步/异步,并发/并行,临界区,阻塞/非阻塞...

    Jave 面试 CAS就这?底层与原理与自旋锁

    CAS底层原理2.1 JMM内存模型(涉及到的知识点)2.2 CAS底层2.3 总结与应用三. 自旋锁SpinLock唉….刚写完了!别白嫖啊,点赞关注,给你们福利啊~~转载请标注! 好兄弟们,不会真有人看不懂CAS吧?反正我是没看懂… 一. CAS...

    Wws_Android_Interview

    面向的复习计划以及相关知识点的总结 预计:1个半月 目录 Java基础:(每周改为三天1.20-12.22)(每周1.20-1.27) 面向对象的特性 集合类 并发(synchroinzed锁机制参考Hencoder Plus?线程安全的集合类) 增加项目...

    java8集合源码分析-LearningNotes:Java笔记

    学习、总结、记录 ! —— since 2018/20 :bar_chart: :hot_beverage: :mobile_phone: :laptop: :floppy_disk:  :pager: :globe_with_meridians: :file_cabinet: :books: :bar_chart: 算法和数据结构 排序算法、...

    sesvc.exe 阿萨德

    codeceo 首页问答热门文章RSS订阅 文章首页 Java JavaScript ... iOS ...2018-07-25 分类:JAVA开发、编程开发、首页精华0人评论 来源:crossoverjie.top ...Map 这样的 Key Value 在软件开发中是非常经典的结构,常...

Global site tag (gtag.js) - Google Analytics