预览加载中,请您耐心等待几秒...
1/10
2/10
3/10
4/10
5/10
6/10
7/10
8/10
9/10
10/10

亲,该文档总共12页,到这已经超出免费预览范围,如果喜欢就直接下载吧~

如果您无法下载资料,请参考说明:

1、部分资料下载需要金币,请确保您的账户上有足够的金币

2、已购买过的文档,再次下载不重复扣费

3、资料包下载后请先用软件解压,在使用对应软件打开

Java的内存模型Java的内存模型在Java语言中,采用的是共享内存模型来实现多线程之间的信息交换和数据同步的。线程之间通过共享程序公共的状态,通过读-写内存中公共状态的方式来进行隐式的通信。同步指的是程序在控制多个线程之间执行程序的相对顺序的机制,在共享内存模型中,同步是显式的,程序员必须显式指定某个方法/代码块需要在多线程之间互斥执行。下面是小编为大家带来的Java的内存模型,欢迎阅读。概述Java内存模型的主要目标是定义程序中各个变量的访问规则,即在JVM中将变量存储到内存和从内存中取出变量这样的底层细节。此处的变量与Java编程里面的变量有所不同,它包含了实例字段、静态字段和构成数组对象的元素,但不包含局部变量和方法参数,因为后者是线程私有的,不会共享,当然不存在数据竞争问题(如果局部变量是一个reference引用类型,它引用的对象在Java堆中可被各个线程共享,但是reference引用本身在Java栈的局部变量表中,是线程私有的)。为了获得较高的执行效能,Java内存模型并没有限制执行引起使用处理器的特定寄存器或者缓存来和主内存进行交互,也没有限制即时编译器进行调整代码执行顺序这类优化措施。JMM规定了所有的变量都存储在主内存(MainMemory)中。每个线程还有自己的工作内存(WorkingMemory),线程的工作内存中保存了该线程使用到的变量的主内存的副本拷贝,线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,而不能直接读写主内存中的变量(volatile变量仍然有工作内存的拷贝,但是由于它特殊的操作顺序性规定,所以看起来如同直接在主内存中读写访问一般)。不同的线程之间也无法直接访问对方工作内存中的变量,线程之间值的传递都需要通过主内存来完成。线程1和线程2要想进行数据的交换一般要经历下面的步骤:1.线程1把工作内存1中的更新过的共享变量刷新到主内存中去。2.线程2到主内存中去读取线程1刷新过的共享变量,然后copy一份到工作内存2中去。内存模型的特性Java内存模型是围绕着并发编程中原子性、可见性、有序性这三个特征来建立的,那我们依次看一下这三个特征:原子性(Atomicity)原子性是指一个操作不能被打断,要么全部执行完毕,要么不执行。在这点上有点类似于事务操作,要么全部执行成功,要么回退到执行该操作之前的状态。基本类型数据的访问大都是原子操作,long和double类型的变量是64位,但是在32位JVM中,32位的JVM会将64位数据的读写操作分为2次32位的读写操作来进行,这就导致了long、double类型的变量在32位虚拟机中是非原子操作,数据有可能会被破坏,也就意味着多个线程在并发访问的时候是线程非安全的。下面我们来演示这个32位JVM下,对64位long类型的数据的访问的问题:【代码1】publicclassNotAtomicity{//静态变量tpublicstaticlongt=0;//静态变量t的get方法publicstaticlonggetT(){returnt;}//静态变量t的set方法publicstaticvoidsetT(longt){NotAtomicity.t=t;}//改变变量t的线程publicstaticclassChangeTimplementsRunnable{privatelongto;publicChangeT(longto){this.to=to;}publicvoidrun(){//不断的将long变量设值到t中while(true){NotAtomicity.setT(to);//将当前线程的执行时间片段让出去,以便由线程调度机制重新决定哪个线程可以执行Thread.yield();}}}//读取变量t的线程,若读取的值和设置的值不一致,说明变量t的数据被破坏了,即线程不安全publicstaticclassReadTimplementsRunnable{publicvoidrun(){//不断的读取NotAtomicity的t的值while(true){longtmp=NotAtomicity.getT();//比较是否是自己设值的其中一个if(tmp!=100L&&tmp!=200L&&tmp!=-300L&&tmp!=-400L){//程序若执行到这里,说明long类型变量t,其数据已经被破坏了System.out.println(tmp);}////将当前线程的执行时间片段让出去,以便由线程调度机制重新决定哪个线程可以执行Thread.yield();}}}publicstaticvoidmain(String[]args){newThread(newChangeT(100L))