Java 内存模型

之我见: java语言去除了指针,使得编程更容易,不必考虑内存的使用和管理工作,但这些工作也是需要有人来做的,这些任务落到了JVM的身上,更具体点是JMM身上。
   Java语言两条机制:
1)    lazyload:在类进行加载时,并不会立即对类的成员变量进行实例化;
2)    JIT编译器代码优化:源程序中代码的顺序,并不等于JVM执行的顺序。这是为了迎合CPU超流水线技术。编译器会调整某些代码的次序,保证程序执行时CPU的指令流水线不会断掉,从而提高执行效率。
   Java并发编程:JVM和JMM来保证java语言的并发编程的线程和内存之间数据交换,同步等繁琐工作。程序只需要利用java线程同步开发包,目前包括:synchronized,wait/notify, threadbarrier,semaphore等

1.    Java 内存模型(java memory model)

http://www.cnblogs.com/uptownBoy/articles/1454441.html

http://blog.csdn.net/wangwenhui11/article/details/6387898


1)    JMM出现的背景

Java语言最大的特点就是废除了指针,把程序员从痛苦中解脱出来,不用再考虑内存使用和管理方面的问题。可惜世事总不尽如人意,虽然JMM设计上方便了程序员,但是它增加了虚拟机的复杂程度,而且还导致某些编程技巧在Java语言中失效。


2)    JMM的功能
JMM主要是为了规定了线程和内存之间的一些关系。对Java程序员来说只需负责用synchronized同步关键字,其它诸如与线程/内存之间进行数据交换/同步等繁琐工作均由虚拟机负责完成。

根据JMM的设计,系统存在一个主内存(Main Memory),Java中所有变量都储存在主存中,对于所有线程都是共享的。每条线程都有自己的工作内存(Working Memory),工作内存中保存的是主存中某些变量的拷贝,线程对所有变量的操作都是在工作内存中进行,线程之间无法相互直接访问,变量传递均需要通过主存完成。


3)     从JMM的角度来重新审视synchronized关键字。
假设某条线程执行一个synchronized代码段,其间对某变量进行操作,JVM会依次执行如下动作(同步经典实例train WC):
(1) 获取同步对象monitor (lock)
(2) 从主存复制变量到当前工作内存 (read and load)
(3) 执行代码,改变共享变量值 (use and assign)
(4) 用工作内存数据刷新主存相关内容 (store and write)

(5) 释放同步对象锁 (unlock)


2.    完成多任务,有 并行和并发两种方式,它们的区别是:
并发(concurrency):一个处理器“同时”处理多个任务。例如,Web并发请求

并行(parallelism):多个处理器或者多核“同时”处理多个任务,例如,大矩阵乘法


3.    Java LazyLoad机制

LazyLoad,这种技巧很常用,就是指一个类包含某个成员变量,在类初始化的时候并不立即为该变量初始化一个实例,而是等到真正要使用到该变量的时候才初始化之。由于LazyLoad可以有效的减少系统资源消耗,提高程序整体的性能,所以被广泛的使用,连Java的缺省类加载器也采用这种方法来加载Java类。在单线程环境下,一切都相安无事,但如果把上面的代码放到多线程环境下运行,那么就可能会出现问题。


4.    Just-in-time (JIT)编译器优化和DCL(Double-Checked Locking)失效

http://developer.51cto.com/art/201105/262573.htm

造成DCL失效的原因之一是编译器的优化会调整代码的次序。只要是在单个线程情况下执行结果是正确的,就可以认为编译器这样的“自作主张的调整代码次序”的行为是合法的。JLS在某些方面的规定比较自由,就是为了让JVM有更多余地进行代码优化以提高执行效率。而现在的CPU大多使用超流水线技术来加快代码执行速度,针对这样的CPU,编译器采取的代码优化的方法之一就是在调整某些代码的次序,尽可能保证在程序执行的时候不要让CPU的指令流水线断流,从而提高程序的执行速度。正是这样的代码调整会导致DCL的失效。参考《DCL Broken Declaration》


5.    Java线程同步增强包

Java用于同步的3板斧:synchronized/wait/notify,它们的确简单而有效。但是在某些情况下,我们需要更加复杂的同步工具。有些简单的同步工具类,诸如ThreadBarrier,Semaphore,ReadWriteLock等,可以自己编程实现。现在要介绍的是牛人Doug Lea的Concurrent包。这个包专门为实现Java高级并行程序所开发,可以满足我们绝大部分的要求。更令人兴奋的是,这个包公开源代码,可自由下载。且在JDK1.5中该包将作为SDK一部分提供给Java开发人员。


6.    Java同步容器类

同步异步影响到的是多线程状态下访问资源的安全性。同步的容器类,实现的访问资源前的加锁和访问资源后的解锁操作,确保了多线程状态下的安全访问,但牺牲了执行效率。Vector和HashTable是同步的,所以Vector和HashTable是线程安全的。


你可能感兴趣的:(Java 内存模型)