解析java中volatile关键字

 更新时间:2016年01月14日 14:21:38   作者:石头_ly  
这篇文章主要为大家解析了java中volatile关键字,经常有人把volatile关键字和synchronized或者lock混淆,本文就为大家好好区分,感兴趣的小伙伴们可以参考一下

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

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实现5种负载均衡算法(小结)

    Java实现5种负载均衡算法(小结)

    负载均衡是将客户端请求访问,通过提前约定好的规则转发给各个server,本文主要介绍了Java实现5种负载均衡算法,具有一定的参考价值,感兴趣的可以了解一下
    2022-06-06
  • JDK8新出Optional类的方法探索与思考分析

    JDK8新出Optional类的方法探索与思考分析

    这篇文章主要为大家介绍了JDK8新出Optional类的发方法示例探索与思考分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • Java反射 PropertyDescriptor类案例详解

    Java反射 PropertyDescriptor类案例详解

    这篇文章主要介绍了Java反射 PropertyDescriptor类案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • IntelliJ IDEA快速查看某个类/接口的子类或父类

    IntelliJ IDEA快速查看某个类/接口的子类或父类

    本文主要介绍了IntelliJ IDEA快速查看某个类/接口的子类或父类,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • Mybatis-plus4条件构造器使用方式

    Mybatis-plus4条件构造器使用方式

    这篇文章主要介绍了Mybatis-plus4条件构造器使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-02-02
  • 常用Java排序算法详解

    常用Java排序算法详解

    本文主要介绍了java的七种常见排序算法的实现,对选择排序、插入排序、冒泡排序、归并排序、快速排序、希尔排序、最小堆排序进行原理分析与实例介绍,具有很好的参考价值。下面就跟着小编一起来看下吧
    2016-12-12
  • Java实现DES加解密算法解析

    Java实现DES加解密算法解析

    这篇文章主要介绍了Java实现DES加解密算法解析,结合完整实例形式分析了DES加密的相关原理,需要的朋友可以参考下。
    2016-10-10
  • Open Feign之非SpringCloud方式使用示例

    Open Feign之非SpringCloud方式使用示例

    这篇文章主要为大家介绍了Open Feign之非SpringCloud方式使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • 一文了解Java Log框架彻底搞懂Log4J,Log4J2,LogBack,SLF4J

    一文了解Java Log框架彻底搞懂Log4J,Log4J2,LogBack,SLF4J

    本文主要介绍了一文了解Java Log框架彻底搞懂Log4J,Log4J2,LogBack,SLF4J,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • SpringBoot RestTemplate GET POST请求的实例讲解

    SpringBoot RestTemplate GET POST请求的实例讲解

    这篇文章主要介绍了SpringBoot RestTemplate GET POST请求的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09

最新评论