多线程基础讲解七: volatile关键字

 

首先volatile关键字有线程安全问题。

volatile有一个专业术语:保证了可见性,不保证原子性。

 

首先不使用volatile关键字,看看有什么效果 

public class NotUseVolatile implements Runnable {

    /**
     * 定义一个非volatile修饰的变量
     */
    private boolean falg = true;

    /**
     * 线程执行代码
     */
    public void run() {
        System.out.println("子线程开始执行");
        while (falg) {

        }
        System.out.println("子线程执行结束");
    }


    /**
     * 生成get set方法
     */
    public boolean isFalg() {
        return falg;
    }

    public void setFalg(boolean falg) {
        this.falg = falg;
    }
}
public class Test {

    public static void main(String[] args) throws InterruptedException {
        NotUseVolatile not = new NotUseVolatile();
        Thread thread = new Thread(not, "不使用volatile关键字的线程");

        thread.start();

        /**
         * 休眠3秒: 如果不休眠,模拟不出这个效果。
         */
        Thread.sleep(3000);
        not.setFalg(false);
        System.out.println("flag值已修改为false");
        Thread.sleep(1000);
        System.out.println("flag值为:" + not.isFalg());


        /**
         * 打印结果:
         *
         *   子线程开始执行
         *   flag值已修改为false
         *   flag值为:false
         *
         * ------------------------------------
         *
         * 有没有发现,flag的值已经修改了,但是线程依然没有结束 ?
         *
         * 这是为什么呢 ?
         *
         * 这里就要说到Java的内存模型了。
         *
         * 注意:
         * Java内存模型:属于线程安全的一个知识点。
         * Java内存结构:属于Jvm的内存分配问题,堆、栈、方法区等。
         *
         * 在java内存模型中,有主内存 和 线程内存两个概念:
         * 全局变量在主内存中,当线程操作全局变量的时候,首先是把全局变量的值复制到线程内存中去,然后线程内存修改之后,再通知主内存修改数据。
         * 所以这里的flag值有几率不会被修改。
         *
         * 但是如果我们要修改线程中的值,怎么办呢 ?
         * 就是再全局变量上加上volatile关键字,当加上了volatile关键字的全局变量被修改后,会去通知线程内存,最后线程内存的值也会修改为主内存所改变的值。
         */

    }
}

 

 

使用volatile关键字:

public class UseVolatile implements Runnable {

    /**
     * 定义一个volatile修饰的变量:
     *
     * 注意:volatile关键字,只保证线程之间的可见性,但是不保证原子性(也就是说线程不安全)
     */
    private volatile boolean falg = true;

    /**
     * 线程执行代码
     */
    public void run() {
        System.out.println("子线程开始执行");
        while (falg) {

        }
        System.out.println("子线程执行结束");
    }


    /**
     * 生成get set方法
     */
    public boolean isFalg() {
        return falg;
    }

    public void setFalg(boolean falg) {
        this.falg = falg;
    }
}
public class Test {

    public static void main(String[] args) throws InterruptedException {
        UseVolatile not = new UseVolatile();
        Thread thread = new Thread(not, "使用volatile关键字的线程");

        thread.start();

        /**
         * 休眠3秒
         */
        Thread.sleep(3000);
        not.setFalg(false);
        System.out.println("flag值已修改为false");
        Thread.sleep(1000);
        System.out.println("flag值为:" + not.isFalg());


        /**
         * 打印结果:
         *   线程开始执行
         *   flag值已修改为false
         *   子线程执行结束
         *   flag值为:false
         *
         * ------------------------------------
         *
         * 使用了volatile关键字后,就达到我们的理想效果了。
         *
         * 注意:volatile有线程安全问题。
         */

    }
}

 

 

所以 volatile的作用是:

每次线程读取全局变量前必须先从主内存刷新最新的值。每次线程写入后必须立即将修改的全局变量同步回主内存当中

 

 


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值