Juc11_Java内存模型之JMM、八大原子操作、三大特性、读写过程、happens-before(二)

③. JVMM规范下,三大特性


①. 可见性


①. 是指当一个线程修改了某一个共享变量的值,其他线程是否能够立即知道该变更,JVMM规定了所有的变量都存储在主内存中


(假设有A、B两个线程同时去操作主物理内存的共享数据number=0,A抢到CPU执行权,将number刷新到自己的工作内存,这个时候进行number++的操作,这个时候number=1,将A中的工作内存中的数据刷新到主物理内存,这个时候,马上通知B,B重新拿到最新值number=1刷新B的工作内存中)


Juc11_Java内存模型之JMM、八大原子操作、三大特性、读写过程、happens-before(二)


②. Java中普通的共享变量不保证可见性,因为数据修改被写入内存的时机是不确定的,多线程并发很可能出现"脏读",所以每个线程都有自己的工作内存,线程自己的工作内存中保存了该线程使用到的变量的主内存副本拷贝,线程对变量的所有操作(读取、赋值等)都必需在线程自己的工作内存中进行,而不能直接读写主内存中的变量。不同线程之间也无法直接访问对工作内存中的变量,线程间变量值的传递均需要通过主内存来完成


volatile可以解决可见性(能否及时看到)


②. 原子性


  • 指一个操作是不可中断的,即多线程坏境下,操作不能被其他线程干扰


③. 有序性


  • ①. 计算机在执行程序时,为了提高性能,编译器和处理器常常会做指令重排,一把分为以下3种


Juc11_Java内存模型之JMM、八大原子操作、三大特性、读写过程、happens-before(二)


  • ②. 单线程坏境里面确保程序最终执行结果和代码顺序执行的结果一致


  • ③. 处理器在进行重新排序是必须要考虑指令之间的数据依赖性


Juc11_Java内存模型之JMM、八大原子操作、三大特性、读写过程、happens-before(二)


④. 多线程坏境中线程交替执行,由于编译器优化重排的存在,两个线程使用的变量能否保持一致是无法确认的,结果无法预测


Juc11_Java内存模型之JMM、八大原子操作、三大特性、读写过程、happens-before(二)


④. JVMM规范下,多线程对变量的读写过程


①. 读取过程


(由于JVM运行程序的实体是线程,而每个线程创建时JVM都会为其创建一个工作内存(有些地方称为栈空间),工作内存是每个线程的私有数据区域,而Java内存模型中规定所有的变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问,但线程对变量的操作(读取赋值等)必须在工作内存中进行,首先要将变量从主内存拷贝到线程自己的工作内存空间,然后对变量进行操作,操作完成后将变量写回主内存,不能直接操作主内存中的变量,各个线程的工作内存中存储着主内存中的变量副本拷贝,因此不同的线程间无法访问对方的工作内存,线程间的通信(传值)必须通过主内存来完成,其简要访问过程如下图)


Juc11_Java内存模型之JMM、八大原子操作、三大特性、读写过程、happens-before(二)



②. JMM定义了线程和主内存之间的抽象关系


线程之间的共享变量存储在主内存中(从硬件角度来说就是内存条)


每个线程都有一个私有的本地工作内存,本地工作内存中存储了该线程用来读/写共享变量的副本(从硬件角度来说就是CPU的缓存,比如寄存器、L1、L2、L3缓存等)


③. 小总结


我们定义的所有的共享变量都存储在物理主内存中


每个线程都有自己独立的工作内存,里面保存该线程使用到的变量的副本(主内存中该变量的一份拷贝)


线程对共享变量所有的操作都必须先在自己的工作内存中进行后写回主内存,不能直接从主内存中读写(不能越级)


不同线程之间也无法直接访问其他线程的工作内存中的变量,线程间变量值的传递需要通过主内存来进行(同级不能相互访问)




上一篇:Sed and awk 笔记之 sed 篇:简单介绍


下一篇:阿里云弹性计算-图形工作站(公测)发布