学习java并发,先了解java内存模型

来源:互联网 发布:java线程之间的通信 编辑:程序博客网 时间:2024/06/05 21:31

一,由于计算机的内存和处理器的计算能力有很大的差距,所以在内存和处理器之间加入一层高速缓存作为缓冲,来解决处理器与内存的速度矛盾:将运算需要使用的数据从内存复制到高速缓存之中,提升运算速度,运算结束之后再将数据同步回内存,这样处理器就不需要等待缓慢的内存读写了。

但是,这时出现一个新的问题:缓存一致性问题。这就需要一种协议保证数据一致性了,这类协议有MSI、MESI、MOSI及Dragon Protocol等。Java虚拟机内存模型中定义的内存访问操作与硬件的缓存访问操作是具有可比性的,下面介绍Java内存模型。

二,JAVA内存模型(java线程之间的通信使用的是共享内存模型,就是指java内存模型JMM)

每个线程都具有自己的工作内存,并可以共享主内存,这个可以和之前的模型进行类比:线程比作处理器,工作线程比作高速缓存,java虚拟机主内存比作计算机内存。

java内存模型实质是定义了程序中各个变量的访问规则,工作内存中保存了该线程需要使用的主内存变量的副本,线程对变量的各种操作都是在工作内存中进行,不能直接操作主内存,将操作之后的工作内存中的副本同步回主内存中,线程之间的通信通过主内存来完成,线程不能直接访问另一个线程的工作内存。

同时这时也会出现和上面出现的缓存一致性问题类似的变量一致性问题。下面介绍java内存模型是如何让变量保持一致的:

主内存和工作内存的交互协议:

1,lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占状态。

2,unlock(解锁):作用于主内存变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。

3,read(读取):作用于主内存变量,把一个变量值从主内存传输到线程的工作内存中,以便随后的load动作使用。

4,load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中。

5,use(使用):作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎,每当虚拟机遇到一个需要使用变量的值的字节码指令时将会执行这个操作。

6,assign(赋值):作用于工作内存的变量,它把一个从线程接收到的值赋值给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。

7,store(存储):作用于工作内存的变量,把工作内存中的一个变量的值传送到主内存中,以便随后的write的操作。

8,write(写入):作用于主内存的变量,它把store操作从工作内存中一个变量的值传送到主内存的变量中。

Java内存模型规定了在执行上述八种基本操作时,必须满足如下规则:

1,不允许read和load、store和write操作之一单独出现,但不需要保证连续,即read和load之间可以插入其他指令。

2,不允许一个线程丢弃它的最近assign的操作,即变量在工作内存中改变了之后必须同步到主内存中。

3,不允许一个线程无原因地(没有发生过任何assign操作)把数据从工作内存同步回主内存中。

4,一个新的变量只能在主内存中诞生,不允许在工作内存中直接使用一个未被初始化(load或assign)的变量。即就是对一个变量实施use和store操作之前,必须先执行过了assign和load操作。

5,一个变量在同一时刻只允许一条线程对其进行lock操作,lock和unlock必须成对出现。

6,如果对一个变量执行lock操作,将会清空工作内存中此变量的值,在执行引擎使用这个变量前需要重新执行load或assign操作初始化变量的值。

7,如果一个变量事先没有被lock操作锁定,则不允许对它执行unlock操作;也不允许去unlock一个被其他线程锁定的变量。

8,对一个变量执行unlock操作之前,必须先把此变量同步到主内存中(执行store和write操作)。

三,java内存模型属于共享内存模型,Java线程之间的通信总是隐式进行,整个通信过程对程序员完全透明。同步是显式进行的,程序员必须显式指定某个方法或某段代码在线程之间互斥执行。



0 0
原创粉丝点击