在Java多线程编程中经常volatile,有时候这个关键字和synchronized 或者lock经常有人混淆,具体解析如下: 

在多线程的环境中会存在成员变量可见性问题: java的每个线程都存在一个线程栈的内存空间,该内存空间保存了该线程运行时的变量信息,当线程访问某一个变量值的时候首先会根据这个变量的地址找到对象的堆内存或者是栈堆存(原生数据类型)中的具体的内容,然后把这个内同赋值一个副本保存在本线程的线程栈中,紧接着对这个变量的一切操作在线程完成退出之前都和堆栈内存中的变量内容是没有关系的,操作的是自己线程栈中的副本。当操作完后会把操作完的结果写回到主内存中。假如有两个线程A和B,同事操作某一个变量x;A对x进行了加1操作,那么B获取的副本可能是x加1后的结果,也可能是x;为了保证获取内存中最新的数据变量
需要加上 volatile 关键字,这样在每次对x进行操作的时候都会去检查下线程栈中的变量的值是不是和住内存中变量的值一样。如果不一样会重新load

public class ThreadSee {
//t1线程会根据flag的值做对应的操作,主线程会更改t1的值
 public static void main(String[] args) throws InterruptedException {
        ThReadTest th=  new ThReadTest();
        Thread t1 = new Thread(th);
        t1.start();
        Thread.sleep(1000);
        th.changeFlag();
        Thread.sleep(2000);
        System.out.println(th.getFlag());
    }

}

class ThReadTest implements Runnable{

   //线程访问变量时会把其load到对应的线程栈中,每次操作时都要获取内存中最新的数据
    private  volatile boolean  stopflag;
    @Override
    public void run() {
        int i=0;
        while(!stopflag){
            i++;
            System.out.println("=="+Thread.currentThread().getName());
        }
        System.out.println("Thread finish:"+i);
    }
    public void changeFlag(){
        this.stopflag=true;
        System.out.println(Thread.currentThread().getName()+"***********");
    }

    public boolean getFlag(){
        return stopflag;
    }
}

上述代码如果去掉volatile,会一直死循环执行下去。 

但是volatile不能保证线程安全的同步 

eg:

public class ThreadSave implements Runnable{
    static ThreadSave sync = new ThreadSave();
    static volatile int j=0;
    //Lock  lock =new ReentrantLock();
    public  void inscane(){
       // lock.lock();
        for(int i=0;i<10000000;i++){
            j++;
        }
     //   lock.unlock();
    }
    @Override
    public void run() {
        inscane();
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(sync);
        Thread t2 = new Thread(sync);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(j);
    }
}

根据上述代码执行的结果不是预期20000000, 

因为对于volatile修饰的变量,jvm虚拟机只是保证从主内存加载到线程工作内存的值是最新的 

例如假如线程1,线程2 在进行线程栈与主内存read,load 操作中,发现主内存中count的值都是5,那么都会加载这个最新的值 

在线程1堆count进行修改之后,会write到主内存中,主内存中的count变量就会变为6 

线程2由于已经进行read,load操作,在进行运算之后,也会更新主内存count的变量值为6 

导致两个线程及时用volatile关键字修改之后,还是会存在并发的情况。 

综上所述: 

volatile只会保证线程去做一个检查当前线程栈的变量值和主内存中数据值是否一样的这么一个动作,只此而已。而lock或者是synchronized 会保证某一时刻只有单个线程进入该方法,从而确保其线程安全性。 

所以在如果多个线程去修改一个volatile变量那么没有实际的逻辑意义。如果一个线程去修改其他的线程依赖修改的变量值,此时是有作用的

解析java中volatile关键字的更多相关文章

  1. 深入解析Java中volatile关键字的作用

    转(http://m.jb51.net/article/41185.htm)Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和 volatile 关键字机制 在java线 ...

  2. 【转】java中volatile关键字的含义

    java中volatile关键字的含义   在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言 ...

  3. 转:java中volatile关键字的含义

    转:java中volatile关键字的含义 在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言 ...

  4. Java中Volatile关键字详解 (转自郑州的文武)

    java中volatile关键字的含义:http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html 一.基本概念 先补充一下概念:J ...

  5. Java中Volatile关键字详解

    一.基本概念 先补充一下概念:Java并发中的可见性与原子性 可见性: 可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉.通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值, ...

  6. java中volatile关键字的理解

    一.基本概念 Java 内存模型中的可见性.原子性和有序性.可见性: 可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉.通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值,有 ...

  7. Java中Volatile关键字详解(转载)

    转载自:https://www.cnblogs.com/zhengbin/p/5654805.html 一.基本概念 先补充一下概念:Java 内存模型中的可见性.原子性和有序性. 可见性: 可见性是 ...

  8. Java中volatile关键字解析

    一.内存模型的相关概念 大家都知道,计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入.由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这时就存 ...

  9. java中volatile关键字的含义

    在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言是支持多线程的,为了解决线程并发的问题,在语 ...

随机推荐

  1. 开发servlet三种方式

    第一种:实现Servlet接口 ServletDemo类 实现Servlet接口 public class ServletDemo implements Servlet { //初始化该servlet ...

  2. centos7 安装elasticsearch

    [root@localhost local]# tar xzvf elasticsearch-2.3.5.tar.gz [root@localhost elasticsearch-2.3.5]# bi ...

  3. Educational Codeforces Round 25 Five-In-a-Row(DFS)

    题目网址:http://codeforces.com/contest/825/problem/B 题目:   Alice and Bob play 5-in-a-row game. They have ...

  4. ssh连接异常:read from socket failed connection reset by peer

    我出现这个问题的原因是:之前将/etc的权限设为777, 这是一个错误的操作!!然后我把权限修改过来(chmod 400 /etc) 重启服务(/bin/systemctl restart ssh.s ...

  5. java.net.UnknownHostException 异常解决方案

    1)使用hostname命令设置新的host name与/etc/hosts本机hostname一致 #hostname 本机hostname 具体可以查看:/etc/hosts和//etc/sysc ...

  6. Ajax的方法和使用代码

    //1.创建Ajax对象,已经封装好的函数: function createXHR(){ if (typeof XMLHttpRequest != "undefined"){ re ...

  7. (转)搬瓦工(bandwagonhost)后台管理VPS

    1. Bandwagonghost使用建议 购买了搬瓦工(bandwagonhost)的VPS,如何使用呢? 首先插几句使用建议,老高认为十分重要,为什么呢?搬瓦工如果监控到有大量的垃圾信息从我们的主 ...

  8. 【ES6】变量的解构赋值

    1. 数组 var [a, b, c] = [1, 2, 3]; let [a, [b], d] = [1, [2, 3], 4]; 默认值生效的条件是,对象的属性值严格等于undefined. [x ...

  9. 【MYSQL】SQL 的join 区别

    ----------------------INNER JOIN---------------------------  1. 三表联合查询 select XX,XX  from a , b , c  ...

  10. Monotonicity 2[POI2010]

    题目描述 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k].选出一个长度为L的子序列(不要求连续),要求这个子序列的第i项和第i+1项的的大小关系为s[(i-1 ...