volatile学习

/**
 * volatile 保证线程的可见性  禁止指令重排
 * 线程可见性:在计算机中每个程序都是运行在自己的本地工作内容中的,同时计算机本身也有自己的主内存,
 *            每个程序需要将主内存中的信息拷贝一份数据到本地内存之中,使用完毕之后再写回给主内存。
 *            因此在线程同步支持的过程中 线程与线程之间的数据是不可见的。 volatile保证了线程之间的可见性。  扩展--MSEI 缓存一致性原理
 *
 * 指令重排:在正常的程序中程序一般都会去顺序从上往下执行,但是编译器有时候不会按照我们代码写的顺序执行。
 *          因此在执行过程中会出现顺序的问题。 使用例子:单例模式
 *          得益于JAVA的 先行发生原则(happen-before原则) 防止指令重拍
 */
public class VolatileJichu {

    volatile boolean flag = true;

    void m (){
        System.out.println("start..");
        while(flag) {

        }
        System.out.println("end...");
    }

    public static void main(String[] args) throws InterruptedException {
        VolatileJichu volatileJichu = new VolatileJichu();
        new Thread(volatileJichu::m, "t").start();
        Thread.sleep(100);
        volatileJichu.flag = false;
    }
}

/**
 * 在非常非常高并发的场景下, 在实例化一个对象可以分为三步,第一步分配内存空间,第二步实例初始化对象,第三步赋值给栈的内存引用
 * 因此当一个线程在初始化对象的时候会发生指令重排,有可能赋值还没有完成,这时候第二个线程获取对象,对象此时所指的是个空对象。导致数据不同。。
 */
public class Singleton {

    private static Singleton singleton;

    //私有构造方法
    private Singleton(){}

    public static Singleton getSingleton(){
        if (singleton == null){
            synchronized (Singleton.class) {
                if (singleton == null){
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(() -> {
                System.out.println(getSingleton().hashCode());
            }).start();
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值