volatile特性及内存语义

1.volatile变量自身具有下列特性:
·可见性:对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入。
·原子性:对任意单个volatile变量的读/写具有原子性,但类似于volatile++这种复合操作不具有原子性。

2.volatile-建立的happens-before关系 :

从内存语义的角度来说,volatile的写-读与锁的释放-获取有相同的内存效果:

                                  volatile写和锁的释放有相同的内存语义;

                                  volatile读与锁的获取有相同的内存语义。

3.volatile-的内存语义 :

写:当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量值刷新到主内存

读:当一个volatileJMM会把该线对应的本地内存置无效线程接下来将从主内存中取共享
 

4.语义总结:

·线A写一个volatile量,实质上是线A向接下来将要读这volatile量的某个线程发出了(其共享量所做修改的)消息。
·线B一个volatile量,实质上是线B接收了之前某个线出的(在写volatile变量之前共享量所做修改的)消息。
·线A写一个volatile量,随后线B读这volatile量,实质上是线A过主内存向线B送消息。 
5.JMM内存屏障插入策略:

·在每个volatile写操作的前面插入一个StoreStore屏障(禁止上面的普通写和下面的volatile写重排序)。

个人见解:每次volatile写操作后都要将本地内存刷新到主内存,所以这里如果不加屏障禁止重排序就可能导致共享变量无法及时对所有线程可见。

·在每个volatile写操作的后面插入一个StoreLoad屏障(禁止上面的volatile写与下面可能有的volatile读/写重排序)。

·在每个volatile操作的后面插入一个LoadLoad屏障(禁止下面所有的普通读写操作和上面的volatile读重排序)和一个LoadStore屏障(禁止下面所有的普通写操作和上面的volatile读重排序)
 个人见解:每次volatile读之前都要将本地内存舍弃去主内存获取最新数据,加屏障禁止重排序的作用是为了保证下面的普通读写的数据不会被舍弃。

 

原文地址:https://www.cnblogs.com/AmbitiousMice/p/8383946.html