JUC Volatile
package com.apple.thread; import java.util.concurrent.atomic.AtomicInteger; /** * This is Description * * @author apple * @date 2020/07/23 */ class MyData { volatile int number = 0; public void addTO60() { this.number = 60; } //请注意此时number前面是添加 volatile 关键字修饰的 public void addPlusPlus() { number++; } AtomicInteger atomicInteger = new AtomicInteger(); public void addAtomic() { atomicInteger.getAndIncrement(); } } /** * 1.验证volatile的可见性 * 1.1假如 int number = 0; number没有添加Volatile修饰 * 1.2 假如 volatile int number = 0; number添加Volatile修饰,添加volatile之后可以解决可见性问题 * <p> * <p> * 2.验证volatile不保证原子性 * 2.1原子性指的是什么意思? * 不可分割,完整性,也即某个线程正在做某个具体业务时,中间不可以被加塞或者被分割,需要整体完整 * 要么同时成功,要么同时失败 * 2.2volatile不保证原子性案例 * <p> * 2.3 why ——> javap 看底层 * <p> * 2.4 如何解决原子性? * (1)加synchronized * (2)使用我们的juc下的AtomicInteger */ public class VolatileDemo { public static void main(String[] args) { //Atomic Data seeAtomicData(); //Volatile seeOKbyVolatile(); } public static void seeAtomicData() { MyData myData = new MyData(); for (int i = 1; i <= 20; i++) { new Thread(() -> { for (int j = 1; j <= 1000; j++) { myData.addPlusPlus(); myData.addAtomic(); } }, String.valueOf(i)).start(); } //需要等待上面20个线程全部计算完成后,再由main线程取得最终的结果,看是多少 //暂停一会儿 while (Thread.activeCount() > 2) { Thread.yield(); } System.out.println(Thread.currentThread().getName() + "\t final number value:" + myData.number); System.out.println(Thread.currentThread().getName() + "\t final number value:" + myData.atomicInteger); } //1.volatile 可以保证可见性,及时通知其他线程,主物理内存的值已经被修改 public static void seeOKbyVolatile() { MyData myData = new MyData();//资源类 new Thread(() -> { System.out.println(Thread.currentThread().getName() + "\t com in "); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } myData.addTO60(); System.out.println(Thread.currentThread().getName() + "\t updated number value:" + myData.number); }, "aaa").start(); while (myData.number == 0) { //main线程一直在这等待循环,直到number值不再等于0 } System.out.println(Thread.currentThread().getName() + "\t mission is over,main get number value:" + myData.number); } }
1.线程在执行的时候,会将主内存(物理内存)的数据进行获取,并存在每个线程自己的工作内存中,修改完成后,再将工作中的内存放回到主内存中
2.volatile修饰的变量特点:”可见性“,没有”原子性“,”禁止指令执行“,但是JVM需要满足所有,那么使用volatile修饰的变量怎么处理?
可以采用:(1)加synchronized (2)使用我们的juc下的 AtomicInteger