您的位置:首页 > 编程语言 > Java开发

java并发内存模型

2016-02-28 16:11 351 查看
java内存模型,基本定义了有共享主存与工作内存。主存相当于堆,工作内存相当于Java线程栈。

而为了解决多个线程并发问题,java定义了6种内存操作指令。

即read,load,use,assigned,store,write.

其中,read表示将主存中的一个变量从主存读取到工作内存中(即线程栈中),load表示将read操作读取到工作内存中的值赋给工作内存中的具体变量。这里是因为一个主存变量在代码中有可能需要同时赋值给方法中多个变量,所以拆分成read与load操作。

use表示将load过来的变量从线程栈读取到虚拟机执行引擎,use之后执行引擎就会将读到的变量进行处理,处理完成之后变会将最终值用assign操作指令赋值回工作内存中的变量。之后,将调用store指令将工作内存中这个被修改的值同步到主存中,最后调用write指令将store那步同步到主存中的值赋值给主存中具体的变量。

并发操作,有三个重要原则,一:原子性,二:可见性,三:有序性。

原子性指的是一个或多个操作是否全部做或全部不做。对于一个变量读取来讲 就是读取到的变量值是完整的,比如一个double变量8个字节,那么虚拟机从主存中读取时一定是读取完整的一个8个字节的内存值。而对于多个操作的原子性通常需要同步块syncronized来完成,它是基于虚拟机提供的monitor enter及monitor exit指令来完成。

可见性指的是一个线程对主存一个共享变量的修改,能够被随后读取它的另一个线程看到。通常volatile及syncronized能够保存可见性。volatile变量通过对于:一个写主存变量的线程,当执行assign之后必须执行store及write(即线程在工作内存中修改了对应主存中变量值时,一定要同步更新回主存),对于一个读主存变量的线程来讲在执行use操作前必须先执行read及load操作(即使用主存变量时必须重新读取主存变量)。对于syncronized来讲,写线程执行完unlock操作,必须将更新的值同步到主存,读线程在执行lock操作时必须从主存同步最新值。

有序性指的是执行代码时的顺序执行,这是由于虚拟机会做一些指令重排的优化。比较典型的一个指令重排问题是:有一个线程负责初始化一些配置信息,初始化后设置一个标记为true表明所有初始化已完成。如果这个标记不是volatile的则会发生设置这个标记为true被执行在初始化配置之前。这样另外一些线程如果根据这个标记为true时认为初始化已完成就做业务操作,就会发生问题。syncronized也能保证有序性,这个是由多个线程竞争同一个锁时,只能保证一个线程能进入同步代码块进行操作。

volatile能保证上面的可见性及有序性,但不能保证原子性。syncronized能保证上面的原子性,可见性,及有序性。

而java中的先行发生原则,指的是,如果a操作先行发生于b操作,那么就是说a操作的结果能被b看到。

而以下情况拥有先行发生原则:

1.同一个线程内的操作,在前面的操作先行发生于后面的操作

2.volatile变量的操作

3.syncronized的操作
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: