volatile特性及内存语义
1.volatile变量自身具有下列特性:
·可见性:对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入。
·原子性:对任意单个volatile变量的读/写具有原子性,但类似于volatile++这种复合操作不具有原子性。
2.volatile写-读建立的happens-before关系 :
从内存语义的角度来说,volatile的写-读与锁的释放-获取有相同的内存效果:
volatile写和锁的释放有相同的内存语义;
volatile读与锁的获取有相同的内存语义。
3.volatile写-读的内存语义 :
写:当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量值刷新到主内存。
读:当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效。线程接下来将从主内存中读取共享变量。
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读之前都要将本地内存舍弃去主内存获取最新数据,加屏障禁止重排序的作用是为了保证下面的普通读写的数据不会被舍弃。