`
lingqi1818
  • 浏览: 252141 次
  • 性别: 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的内存模型保证这一点)
分享到:
评论

相关推荐

    day18_等待唤醒、JMM、并发编程特性、volatile.pdf

    《Java并发编程:等待唤醒机制、内存模型及volatile》 ...总结,Java的等待唤醒机制、内存模型和并发编程特性是构建高效并发程序的关键。通过理解和运用这些概念,开发者可以编写出更加健壮和高效的多线程程序。

    【java模拟器】最新最完美的JAVA模拟器JMM_SmartPhone_2003_SmartPhone_5.0_SmartPhone_6.0

    总结来说,JMM_SmartPhone是一款强大的Java模拟器,它支持多个版本的SmartPhone操作系统,为开发者提供了在桌面环境中测试和优化Java ME应用程序的平台。通过使用该模拟器,开发者可以有效地提高代码质量和用户体验...

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

    Java内存模型(JMM)是Java编程语言中用于规定如何处理多线程环境下共享变量的访问规则的一个抽象概念。它的设计目标是确保在各种硬件和操作系统平台上,Java程序的执行行为具有可预测性,同时也允许编译器和处理器...

    Java内存模型精辟总结

    Java内存模型(JMM)是Java编程中的一个重要概念,它规定了程序中各个变量的访问规则,尤其是在多线程环境下如何保证数据的一致性和可见性。JMM的目标是为了解决由于编译器优化、处理器缓存和多处理器系统间的内存...

    最新Java面试八股文10万字总结

    理解并发模型和JVM内存模型(JMM)有助于解决多线程问题。 Java反射机制允许程序在运行时检查和修改自身的行为,面试中可能会考察Class类、Constructor、Method和Field的使用。垃圾收集(GC)和内存管理也是面试的...

    java线程安全总结

    3. **Happens-Before原则**:JMM定义了一组规则来确保一些操作按一定的顺序执行,从而保证了变量的可见性。 - **2.2 有序性** 有序性是指程序执行的顺序按照代码的先后顺序执行。在单线程环境中,代码的执行顺序...

    java复习总结,含编写习惯,教程开发

    这篇复习总结将深入探讨Java的核心概念,编程习惯以及实际开发过程中的关键知识点。 首先,"Java编写习惯"是成为一名优秀Java程序员的基础。良好的代码风格不仅使代码更易读,而且有助于团队协作和后期维护。遵循...

    Java高频核心面试总结完整版

    再者,Java内存模型(JMM)是理解多线程中数据同步的基础。它定义了线程如何访问和修改共享变量,以及何时能看到其他线程对这些变量的修改。volatile关键字保证了变量的可见性和有序性,但不保证原子性;而Atomic类...

    java学习资料总结

    Java学习资料总结主要聚焦在Java多线程领域,是一份深度探索Java并发编程的资源集合。这份资料旨在帮助初学者和有一定经验的开发者系统性地理解并掌握Java中的多线程概念和技术,提升并发编程能力。 首先,"前言...

    社招面试经验总结.pdf

    【社招面试经验总结】 社招面试是企业面向社会广泛招募人才的过程,不同于校招,它通常针对有一定工作经验的专业人士。面试者需要具备扎实的专业技能和丰富的实战经验。以下是一些重要的面试知识点: 1. **Java...

    2020年最新版--Java+最常见的+200++面试题汇总+答案总结汇总

    设计模式是解决软件设计中常见问题的经验总结,面试中可能会问到单例模式、工厂模式、装饰者模式、观察者模式、代理模式等。理解这些模式的意图、结构和实现方式将有助于解答相关问题。 【Spring框架】 Spring是...

    什么是Java内存模型.docx

    5. **重排序(Reordering)**:为了优化性能,编译器和处理器可能会对指令进行重排序,但JMM规定了一些限制,以保证在特定条件下重排序不会破坏程序的正确性。 在多线程环境下,JMM通过内存屏障(Memory Barrier)...

    数据的强弱一致性介绍与总结

    在JMM中,线程有自己的工作内存(如CPU缓存),共享变量则存储在主内存(堆内存或方法区)中。当线程读写共享变量时,会先将其加载到工作内存,然后在工作内存中进行操作,最后将结果写回主内存。这个过程可能会出现...

    Java线程内存模型的缺陷.docx

    尽管JMM的设计初衷是简化多线程编程的复杂性,但实际应用中仍存在一些难以避免的问题: 1. **数据不一致性**:当多个线程并行执行时,由于线程的工作内存与主内存之间的数据交换是松散耦合的,可能会导致不同线程间...

Global site tag (gtag.js) - Google Analytics