Java中的volatile关键字解析

 更新时间:2023年11月01日 08:38:01   作者:南瓜灯cc  
这篇文章主要介绍了Java中的volatile关键字解析,Java内存模型规定了所有的变量都存储在主内存中,每个线程都有自己的工作内存,线程的工作内存保存了该线程使用到的变量的是主内存副本的拷贝,需要的朋友可以参考下

volatile关键字

在对该关键字进行认识之前,需要对Java内存模型有一定的认识。 Java内存模型规定了所有的变量都存储在主内存中,每个线程都有自己的工作内存,线程的工作内存保存了该线程使用到的变量的是主内存副本的拷贝,线程对于变量的操作(读取,复制)都必须在工作内存中进行,而不能直接读写主内存中的变量。

这里写图片描述

在进行变量操作的时候,如果每次都是从主内存中读写,无疑是影响性能的, 即一个线程在操作某一个变量之前,会先把变量的值从主内存中拷贝一个副本放到工作内存中,操作完成之后同步到主内存中。不同的线程之间无法直接访问对方工作内存中的变量,线程间变量值的传递均需要通过主内存来完成。

volatile: 当一个变量被定义为volatile(不稳定的)之后,线程在进行变量操作的时候,都不会使用本地内存中之前缓存的数据,而是每次都会从主内存中把变量的值拷贝副本到工作内存中,这样就保证了变量对于所有线程的可见性。

public class TestVolatile {
     public static void main(String[] args) throws Exception {
         ThreadDemo td=new ThreadDemo();
         Thread t=new Thread(td);
         t.start();
         while(true){
             if(td.isFlag()){
                 System.out.println("OK");
                 break;
             }
         }
    }    
}

class ThreadDemo implements Runnable{
    private volatile boolean flag=false;
    @Override
    public void run() {
        try {
            Thread.sleep(2000); 
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        flag=true;
        System.out.println("flag="+isFlag());
    }


    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}

需要特别注意的是, 即使volatile能够保证其变量对于线程的可见性,但是却不能保证并发的安全性。

比如多线程执行线程执行i++(i假设用volatilex修饰)也不能保证其安全性。 如下图:

这里写图片描述

因为i++并不是原子性的操作,当一个线程A再工作内存中进行数据操作的时候,还未结束的时候,cpu切换到了另一个线程B,而此时之前i++操作并没有结束,即并没有把数据刷新到主内存中,此时B获取到的数据跟A获取的数据实际上是一样的,这时候就存在了并发的问题了。

到此这篇关于Java中的volatile关键字解析的文章就介绍到这了,更多相关Java中的volatile内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Springboot详解RocketMQ实现消息发送与接收流程

    Springboot详解RocketMQ实现消息发送与接收流程

    这篇文章主要介绍了SpringBoot整合RocketMQ实现消息发送和接收功能,我们使用主流的SpringBoot框架整合RocketMQ来讲解,使用方便快捷,本文分步骤给大家介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • 解决mapstruct在eclipse生成不了mapper的实现类问题

    解决mapstruct在eclipse生成不了mapper的实现类问题

    这篇文章主要介绍了解决mapstruct在eclipse生成不了mapper的实现类问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • SpringBoot模拟员工数据库并实现增删改查操作

    SpringBoot模拟员工数据库并实现增删改查操作

    这篇文章主要给大家介绍了关于SpringBoot模拟员工数据库并实现增删改查操作的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2021-09-09
  • SpringBoot WebSocket实时监控异常的详细流程

    SpringBoot WebSocket实时监控异常的详细流程

    最近做了一个需求,消防的设备巡检,如果巡检发现异常,通过手机端提交,后台的实时监控页面实时获取到该设备的信息及位置,然后安排员工去处理。这篇文章主要介绍了SpringBoot WebSocket实时监控异常的全过程,感兴趣的朋友一起看看吧
    2021-10-10
  • Java代码执行shell命令的实现

    Java代码执行shell命令的实现

    这篇文章主要介绍了Java代码执行shell命令的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • Spring Boot使用Druid进行维度的统计和监控

    Spring Boot使用Druid进行维度的统计和监控

    这篇文章主要介绍了Spring Boot使用Druid进行维度的统计和监控,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-04-04
  • springboot的实体类字段校验的分组校验具体实现步骤

    springboot的实体类字段校验的分组校验具体实现步骤

    分组校验允许在不同场景下对同一实体类应用不同的校验规则,通过定义分组接口、在实体类和Controller中指定分组,以及全局异常处理,可以灵活控制校验规则,本文介绍springboot的实体类字段校验的分组校验,感兴趣的朋友一起看看吧
    2025-03-03
  • Jackson java动态去除返回json中的值方式

    Jackson java动态去除返回json中的值方式

    文章介绍了在Java中使用@JsonInclude注解动态去除返回JSON中的非必需字段(如分页信息)的解决方案,通过在字段上添加@JsonInclude注解并选择合适的策略(如NON_NULL或NON_EMPTY),可以在非分页情况下取消分页字段,从而提高返回结果的灵活性和效率
    2024-12-12
  • 详解Java中@Override的作用

    详解Java中@Override的作用

    这篇文章主要介绍了详解Java中@Override的作用的相关资料,希望通过本文能帮助到大家,让大家理解这部分内容,需要的朋友可以参考下
    2017-10-10
  • Java获取最后插入MySQL记录的自增ID值的3种方法

    Java获取最后插入MySQL记录的自增ID值的3种方法

    这篇文章介绍了Java获取最后插入MySQL记录的自增ID值的3种方法,有需要的朋友可以参考需要
    2013-08-08

最新评论