JAVA多线程之——volatile关键字

来源:互联网 发布:剑灵天女捏脸数据图片 编辑:程序博客网 时间:2024/05/29 08:57

概要
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();        }    }}

运行结果:

2000423653055638663830008152200090598433

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

0 0
原创粉丝点击