解析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中断线程的方法

    Java中断线程的方法

    这篇文章主要介绍了Java中断线程的方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-05-05
  • Spring Boot Thymeleaf实现国际化的方法详解

    Spring Boot Thymeleaf实现国际化的方法详解

    这篇文章主要给大家介绍了关于Spring Boot Thymeleaf实现国际化的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Spring Boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-10-10
  • Spring Cloud动态配置刷新@RefreshScope与@Component的深度解析

    Spring Cloud动态配置刷新@RefreshScope与@Component的深度解析

    在现代微服务架构中,动态配置管理是一个关键需求,Spring Cloud 提供了 @RefreshScope 注解,允许应用在运行时动态更新配置,而无需重启服务,本文深入探析Spring Cloud动态配置刷新@RefreshScope与@Component,感兴趣的朋友一起看看吧
    2025-04-04
  • MybatisPlus之likeRight的用法

    MybatisPlus之likeRight的用法

    这篇文章主要介绍了MybatisPlus之likeRight的用法说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • Java注解方式之防止重复请求

    Java注解方式之防止重复请求

    这篇文章主要介绍了关于Java注解方式防止重复请求,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • Java 多线程并发ReentrantLock

    Java 多线程并发ReentrantLock

    这篇文章主要介绍了Java 多线程并发ReentrantLock,Java 提供了 ReentrantLock 可重入锁来提供更丰富的能力和灵活性,感兴趣的小伙伴可以参考一下
    2022-06-06
  • java事件处理模型知识点总结

    java事件处理模型知识点总结

    在本篇文章里小辫给大家分享的是一篇关于java事件处理模型知识点总结内容,有兴趣的朋友们可以学习下。
    2021-01-01
  • Spring boot中使用Spring-data-jpa方便快捷的访问数据库(推荐)

    Spring boot中使用Spring-data-jpa方便快捷的访问数据库(推荐)

    Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据的访问和操作。这篇文章主要介绍了Spring-boot中使用Spring-data-jpa方便快捷的访问数据库,需要的朋友可以参考下
    2018-05-05
  • 基于Java编写串口通信工具

    基于Java编写串口通信工具

    这篇文章主要为大家详细介绍了基于Java编写的一个带有图形界面的简单串口通信工具,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • 浅谈Ribbon、Feign和OpenFeign的区别

    浅谈Ribbon、Feign和OpenFeign的区别

    这篇文章主要介绍了浅谈Ribbon、Feign和OpenFeign的区别。具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06

最新评论