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

posted @ 2020-07-23 17:59  alen-fly  阅读(108)  评论(0编辑  收藏  举报