本文转载自公众号:石杉的架构笔记,阅读大约需要7分钟。

一、写在前面

前段时间把几年前带过的一个项目架构演进的过程整理了一个系列出来,参见(《亿级流量架构系列专栏总结》)。

不过很多同学看了之后,后台反馈说文章太烧脑,看的云里雾里。其实这个也正常,文章承载的信息毕竟有限,而架构的东西细节太多,想要仅仅通过文章看懂一个系统架构的设计和落地,确实难度不小。

所以接下来用大白话跟大家聊点轻松的话题,比较易于理解,而且对大家工作和面试都很有帮助。

二、场景引入,问题初现

第一,一旦data变量定义的时候前面加了volatile来修饰的话,那么线程1只要修改data变量的值,就会在修改完自己本地工作内存的data变量值之后,强制将这个data变量最新的值刷回主内存,必须让主内存里的data变量值立马变成最新的值!

整个过程,如下图所示:

2

第二,如果此时别的线程的工作内存中有这个data变量的本地缓存,也就是一个变量副本的话,那么会强制让其他线程的工作内存中的data变量缓存直接失效过期,不允许再次读取和使用了!

整个过程,如下图所示:

3

第三,如果线程2在代码运行过程中再次需要读取data变量的值,此时尝试从本地工作内存中读取,就会发现这个data = 0已经过期了!

此时,他就必须重新从主内存中加载data变量最新的值!那么不就可以读取到data = 1这个最新的值了!整个过程,参见下图:

bingo!好了,volatile完美解决了java并发中可见性的问题!

对一个变量加了volatile关键字修饰之后,只要一个线程修改了这个变量的值,立马强制刷回主内存。

接着强制过期其他线程的本地工作内存中的缓存,最后其他线程读取变量值的时候,强制重新从主内存来加载最新的值!

这样就保证,任何一个线程修改了变量值,其他线程立马就可以看见了!这就是所谓的volatile保证了可见性的工作原理!

四、总结 & 提醒

最后给大家提一嘴,volatile主要作用是保证可见性以及有序性。

有序性涉及到较为复杂的指令重排、内存屏障等概念,本文没提及,但是volatile是不能保证原子性的

也就是说,volatile主要解决的是一个线程修改变量值之后,其他线程立马可以读到最新的值,是解决这个问题的,也就是可见性!

但是如果是多个线程同时修改一个变量的值,那还是可能出现多线程并发的安全问题,导致数据值修改错乱,volatile是不负责解决这个问题的,也就是不负责解决原子性问题!


原子性问题,得依赖synchronized、ReentrantLock等加锁机制来解决。

下方查看历史文章

99.9%的Java程序员都说不清的问题:JVM中的对象内存布局?

ThreadLocal:Java中的影分身

【译】Linux概念架构的理解

阿里面试题:使用数组实现一个简单的阻塞队列

本号专注于后端技术、JVM问题排查和优化、Java面试题、个人成长和自我管理等主题,为读者提供一线开发者的工作和成长经验,期待你能在这里有所收获。

Java并发面试问题之volatile到底是什么?的更多相关文章

  1. 并发系列1----大白话聊聊Java并发面试问题之volatile到底是什么?【石杉的架构笔记】

  2. Java并发编程之三:volatile关键字解析 转载

    目录: <Java并发编程之三:volatile关键字解析 转载> <Synchronized之一:基本使用>   volatile这个关键字可能很多朋友都听说过,或许也都用过 ...

  3. Java并发编程之验证volatile不能保证原子性

    Java并发编程之验证volatile不能保证原子性 通过系列文章的学习,凯哥已经介绍了volatile的三大特性.1:保证可见性 2:不保证原子性 3:保证顺序.那么怎么来验证可见性呢?本文凯哥(凯 ...

  4. 【搞定 Java 并发面试】面试最常问的 Java 并发进阶常见面试题总结!

    本文为 SnailClimb 的原创,目前已经收录自我开源的 JavaGuide 中(61.5 k Star![Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识.觉得内容不错 ...

  5. Java并发编程学习:volatile关键字解析

    转载:https://www.cnblogs.com/dolphin0520/p/3920373.html 写的非常棒,好东西要分享一下 Java并发编程:volatile关键字解析 volatile ...

  6. java并发面试

    1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户线程(User). 任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon( ...

  7. Java并发编程基础之volatile

    首先简单介绍一下volatile的应用,volatile作为Java多线程中轻量级的同步措施,保证了多线程环境中“共享变量”的可见性.这里的可见性简单而言可以理解为当一个线程修改了一个共享变量的时候, ...

  8. 干货:Java并发编程系列之volatile(二)

    接上一篇<Java并发编程系列之synchronized(一)>,这是第二篇,说的是关于并发编程的volatile元素. Java语言规范第三版中对volatile的定义如下:Java编程 ...

  9. Java并发编程里的volatile。Java内存模型核CPU内存架构的对应关系

    CPU内存架构:https://www.jianshu.com/p/3d1eb589b48e Java内存模型:https://www.jianshu.com/p/27a9003c33f4 多线程下的 ...

随机推荐

  1. mui或者uni退出app

    在安卓上可以使用 //1.1 var backButtonPress = 0; $.back = function(event) { backButtonPress++; if(backButtonP ...

  2. 使用Git Flow进行版本控制

    重置 # force reset $ git flow init -f

  3. vue文件夹上传组件选哪个好?

    一. 功能性需求与非功能性需求 要求操作便利,一次选择多个文件和文件夹进行上传:支持PC端全平台操作系统,Windows,Linux,Mac 支持文件和文件夹的批量下载,断点续传.刷新页面后继续传输. ...

  4. 从三数之和看如何优化算法,递推-->递推加二分查找-->递推加滑尺

    人类发明了轮子,提高了力的使用效率. 人类发明了自动化机械,将自己从重复的工作中解脱出来. 提高效率的方法好像总是离不开两点:拒绝无效劳动,拒绝重复劳动.人类如此,计算机亦如是. 前面我们说过了四数之 ...

  5. Layui 隐藏左侧菜单

    简单实现 //隐藏菜单 var bl = $("#LAY_app_flexible").hasClass("layui-icon-shrink-right"); ...

  6. C++中静态成员变量要在类外部再定义或初始化的原因

    C++中静态成员变量要在类外部再定义或初始化,否则会产生错误. class A { public: static int a; }; int A::a=0; 为什么要在类的外部进行定义的原因: 1. ...

  7. React_01_ECMAScript6

    ECMAScript6 1.ES6简介 1.1.什么是ES6 ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了.它的目 ...

  8. MySQL错误ERROR 1786 (HY000)解决

    务上需要支持create table XXX as select * from XXX; 这种创建表的语法,但是MySQL5.7.x版本里面gtid是开启的,会报错 ERROR 1786 (HY000 ...

  9. [技术博客]阿里云签名机制字符串的C语言实现

    [技术博客]阿里云签名机制字符串的C语言实现 问题描述见:阿里云签名机制 话不多说,上字符串函数转化函数代码 bool AlicloudRequest::sendV2Request() { if( q ...

  10. CentOS7安装RabbitMQ,并设置远程访问

      如果网速慢 可以直接到百度云分享中下载,然后拉到centerOS中,进行第二步即可    两个人安装包地址,提取码:z1oz 1.安装erlang环境 wget http://www.rabbit ...