Java并发-1(一)内存可见性

线程学习之后,大概了解了线程的功能和原理,这里不再赘述。

什么是内存可见性呢?

当若干个线程共享同一个资源的时候,这个资源就处于临界状态,如果处理不当很容易发生一些不愿意看到的错误。

举个栗子:

  1. 创建一个ThreadDemo类实现Runnable接口
  2. 有一个boolean的变量flg默认值是false
  3. 在run()方法中改变flg的值为true
  4. 然后在main方法中创建一个线程执行start方法
  5. 在线程中判断flg的值是否是true,并打印语句
class ThreadDemo implements Runnable{

    private  boolean flg = false;

    @Override
    public void run() {

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        this.flg = true;
        System.out.println("ThreadDemo.run()->flg:"+this.flg);
    }

    public boolean isFlg() {
        return flg;
    }

    public void setFlg(boolean flg) {
        this.flg = flg;
    }
}

TestVolatile类和main方法

public class TestVotile {


    public static void main(String[] args) {
        ThreadDemo td = new ThreadDemo();
        new Thread(td).start();

        while(true){
            if(td.isFlg()){
                System.out.println("CurrentThread->");
                break;
            }
        }
    }

}

执行main方法之后观察测试结果:

结果令人感到意外?而且发现eclipse上的红色按钮表示程序并没有结束而是一直再循环。

原因分析

在多线程中JVM虚拟机为了优化和提高效率,为每一个线程都提供了一个单独的缓存空间。这样在这个例子中共享变量flg就产生了三个空间,一个是主存,在堆中,另外两个一个在线程td的缓存中,另外一个在main线程的缓存中。

如图所示:
这里写图片描述
在td线程拿到flg之后放在自己的缓存中,并且修改flg为true然后把修改后的值刷新到主内存中,但是由于main线程的while循环效率非常高,在主内存的值被刷新之前就获得到了flg的值,为false,所以不会执行打印语句,即便是主存中的flg值已经被刷新了,但是由于while的影响,没机会在主内存中多的最新的值,导致flg在main的while中一直是false,一直处于循环状态什么都不做。而且主线程也不会结束。

volatile关键字

对于上属于的问题就是内存可见性的问题,在TreadDemo类想flg变量之前加上volatile修饰符,使得双方的操作的共享资源可以及时的得到更新,甚至可以看成双方对共享资源的操作就是指主存中进行的,而且共享资源的的改变可以被任何一个线程得到,这样就保证了内存的可见性。

class ThreadDemo implements Runnable{

    private  volatile boolean flg = false;

    @Override
    public void run() {

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        this.flg = true;
        System.out.println("ThreadDemo.run()->flg:"+this.flg);
    }

    public boolean isFlg() {
        return flg;
    }

    public void setFlg(boolean flg) {
        this.flg = flg;
    }
}

再次测试输出结果为

这里写图片描述

此时线程结束,主线程也打印了语句。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值