上节的代码,让我们理解了主内存和工作内存的关系
接下来我们结合volatile来解决一些上节未解决的问题
volatile特性
1、强制将修改的值写入内存
2、当线程2修改变量值时,会导致线程1的工作内存的缓存失效
3、由于线程1的缓存变量失效,线程1会从主存再次读取
volatile是java中最轻量级的同步机制,当一个变量被volatile修饰后,它有两个特性:
可见性:保证变量对所有线程可见的,这里可见是指一个线程修改了值,这个修改对其他线程来说是立即可知的。
禁止指令重新排序优化:避免了多线程环境下程序出现乱序执行的现象
volatile原理和实现机制
加了volatile关键词,字节码文件会加一个lock关键词
lock指令实际上相当于一个内存屏障(也称内存栅栏),内存屏障提供三个功能:
1)、它确保指令重排时,不会把其后的指令排到屏障之前的位置,也不会把其前的指令放到屏障之后,即执行到内存屏障这句指令时,在它前边的操作已经完成。
2)、它会强制对缓存修改操作立即写入主存。
3)、如果是写操作,它会导致其他cpu中对应的缓存行失效。
volatile和synchronized来比,更加轻量级,因为它不会像synchronized一样阻塞,但是它不是什么场景都适合,volatile无法保证原子性,synchronized能保证三种特性,所以我们要具体情况具体分析。
代码上节问题:
package com.fyd; public class JVMMOdelTest { public static void main(String[] args) { JVMModel jvmModel = new JVMModel(); new Thread(jvmModel).start(); while (true) { if (jvmModel.isFlag()) { System.out.println("------"); break; } } } } class JVMModel implements Runnable { private volatile boolean flag = false; @Override public void run() { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } flag = true; System.out.println(Thread.currentThread().getName() + ":" + flag); } public boolean isFlag() { return flag; } }