JAVA多线程之——volatile关键字

30 篇文章 0 订阅

概要
volatile关键字主要作用是使变量在多个线程之间可见。
在线程工作的时候,每个线程都会有自己的一个内存区域,这个区域保存了主内存中线程需要用到的一些变量和引用。当多个线程访问一个没有同步的变量时候,每个线程自己内存中的变量对于其它线程是不可见的。如图:
这里写图片描述
图中线程1与线程2的count变量是互不可见的。
但是,当一个变量如果被volatile修饰之后。那么多个线程之间对于这个变量则是互相可见的。因为当一个变量被volatile修饰之后,那么任何线程在load这个变量的时候,编译器会强制所有线程读取这个变量都从主内存中去读取。这样每个线程读取的都会是一样的数据。示例:

public class MyThread  implements Runnable {

    private  boolean isRunning = true;
    public  void setRunning(boolean isRunning) {
        this.isRunning = isRunning;
    }

    @Override
    public void run() {
        System.out.println("开始运行。。。。。");
        while(isRunning) {
        }
        System.out.println("终止运行。。。。。");
    }


    public static void main(String[] args) throws InterruptedException {
        MyThread myThread = new MyThread();
        Thread t1 = new Thread(myThread);
        t1.start();
        t1.sleep(2000);
        myThread.setRunning(false);
        System.out.println("设置运行结束");
        t1.sleep(1000);
        System.out.println("当前isRunning = " + myThread.isRunning);
    }

}

代码运行结果:
这里写图片描述
可以看到设置了isRunning为false。程序并没有退出。这说明t1线程读取的是自身的内存变量。不是主内存。

volatile具有可见性,但不具有原子性
volatile只能让多个线程之间具有可见性,并不能具有原子性。示例:

public class MyThread  extends Thread {

    private static volatile int count  ;

    public static void add()  {
        for(int i = 0 ; i < 1000; i++){
            count++;
        }
        System.out.println(count);
    }
    @Override
    public void run() {
            add();
    }


    public static void main(String[] args) throws InterruptedException {

        MyThread[]  threads = new MyThread[10];
        for(int j = 0; j < 10; j++) {
            threads[j] = new MyThread();
        }
        for(int i = 0; i < 10; i++) {
            threads[i].start();
        }

    }

}

运行结果:

2000
4236
5305
5638
6638
3000
8152
2000
9059
8433

运行结果并没有是10000.这说明volatile关键字修饰变量并不具有原子性。其原因是因为对于对一个变量进行操作时。内存的操作步骤是:
read and load 从主存复制变量到当前工作内存
use and assign 执行代码,改变共享变量值
store and write 用工作内存数据刷新主存相关内容
但是这一些操作并不是原子性,也就是 在read load之后,如果主内存count变量发生修改之后,线程工作内存中的值由于已经加载,不会产生对应的变化,所以计算出来的结果会和预期不一样。具体详细分析,以后在学习JVM中会进行具体分析。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值