线程解锁前,必须把共享变量立刻刷回主存。
线程加锁前,必须读取主存中的最新值到工作内存中!
加锁和解锁是同一把锁。
public class VolatileTest { // 不加 volatile 程序就会死循环! // 加 volatile 可以保证可见性 private static int sum=0; public static void main(String[] args) { new Thread(()->{ while (sum==0){ } }).start(); try{ TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } sum=1; System.out.println(sum); } }
运行结果:
②、使用了volatile关键字,线程可以得知主内存的变化
public class VolatileTest { // 不加 volatile 程序就会死循环! // 加 volatile 可以保证可见性 private volatile static int sum=0; public static void main(String[] args) { new Thread(()->{ while (sum==0){ } }).start(); try{ TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } sum=1; System.out.println(sum); } }
运结果:
public class VolatileTest2 { private volatile static int num=0; public static void add(){ num++; } //理论上值应该为20000 public static void main(String[] args) { for (int i=1;i<=20;i++){ new Thread(()->{ for (int j=1;j<=1000;j++){ add(); } }).start(); } //判断剩下的线程是否大于2个,如果大于则表明20个线程创建成功了 while (Thread.activeCount()>2){ Thread.yield(); } System.out.println(Thread.currentThread().getName()+"---->"+num); } }
运行结果:
②、使用AtomicInteger保证其原子性
public class VolatileTest2 { private volatile static int num=0; private volatile static AtomicInteger atomicInteger= new AtomicInteger(); public static void add(){ // AtomicInteger + 1 方法, CAS atomicInteger.getAndIncrement(); } //理论上值应该为20000 public static void main(String[] args) { for (int i=1;i<=20;i++){ new Thread(()->{ for (int j=1;j<=1000;j++){ add(); } }).start(); } //判断剩下的线程是否大于2个,如果大于则表明20个线程创建成功了 while (Thread.activeCount()>2){ Thread.yield(); } System.out.println(Thread.currentThread().getName()+"---->"+atomicInteger); } }
运行结果:
线程A | 线程B |
---|---|
x = a | y = b |
b =1 | y = b |
线程A | 线程B |
---|---|
b =1 | y = b |
x = a | y = b |