volatile说明

在变量中声明后,能够在所有线程中共享改变量。并且volatile关键字能防止指令重排,即程序读取到volatile时,则不会将程序执行顺序修改。

先了解下内存模型

cpu内存模型

多核cpu在处理数据时,会通过系统总线把主内存中的数据读取副本到高速缓存中的缓存行,当其中一个cpu修改了当前缓存行的数据,会有两种方式保证数据的一致性

1、总线锁:因为高速缓存交互主存是需要通过系统总线的,所以修改后会将总线锁定,阻塞其它CPU访问主存,等当前CPU缓存写入到主存后释放锁。其它CPU才能从主存中读取数据。这种方式效率极低,影响其它CPU访问内存。

2、缓存一致性(MESI):当前CPU缓存行数据修改,通过总线将修改状态广播给其它CPU,让各个CPU根据状态判断本地情况进行响应,是失效还是重新读

java内存模型

JVM内存结构,把内存分为 堆、栈、方法区、本地方法栈和程序计数器。其中堆和方法区被所有线程共享,在内存模型中被成为主内存,而栈、程序计数器属于线程私有,在内存模型中被成为工作内存。

  Java内存模型规定所有的变量都是存在主存当中(类似于前面说的物理内存),每个线程都有自己的工作内存(类似于前面的高速缓存)。线程对变量的所有操作都必须在工作内存中进行,而不能直接对主存进行操作。并且每个线程不能访问其他线程的工作内存。

volatile作用

java中内存模型没有像CPU一样的总线来保证线程数据共享。这时候就需要volatile,volatile会强制将每个线程工作内存的变量修改主动的保存主存中。要读取时再从主存中读取

使用volatile达到的线程间变量共享的问题。但是无法保证数据原子性

因为多个线程同时执行,读取赋值写入,那么volatile修饰的变量则会已程序执行时的最后一个线程修改的参数为准。

保障volatile原子性

保障原子性的方式有三种synchronized、lock、atomic

两者是锁住当前变量的操作线程。

atomic是java提供的CAS来实现原子性操作

应用场景

需要通过某个状态控制调用volatile变量的线程(只有一个线程写,其它线程读)

与static区别

相同点:

1、都是为了保证线程共享

2、非原子性(操作变量)

不同点:

volatile唯一的好处就是多线程可以及时获取到最新的主存数据,这点跟static有点区别。static在多线程状态下可能获取不到最新数据。

JVM规范定义了线程对内存间交互操作:
Lock(锁定):作用于主内存中的变量,把一个变量标识为一条线程独占的状态。
Read(读取):作用于主内存中的变量,把一个变量的值从主内存传输到线程的工作内存中。
Load(加载):作用于工作内存中的变量,把read操作从主内存中得到的变量的值放入工作内存的变量副本中。
Use(使用):作用于工作内存中的变量,把工作内存中一个变量的值传递给执行引擎。
Assign(赋值):作用于工作内存中的变量,把一个从执行引擎接收到的值赋值给工作内存中的变量。
Store(存储):作用于工作内存中的变量,把工作内存中的一个变量的值传送到主内存中。
Write(写入):作用于主内存中的变量,把store操作从工作内存中得到的变量的值放入主内存的变量中。
Unlock(解锁):作用于主内存中的变量,把一个处于锁定状态的变量释放出来,之后可被其它线程锁定。

上面一段,只要知道,工作内存中保留了一份主存中的变量副本,因此写操作未必能马上更新到主存,读操作也未必能马上读取到主存中更新后的值,这与cpu时间片有关,能不能读取最新的值看缘分。

参考:

static和volatile的原理及区别:https://blog.csdn.net/x18094/article/details/108429511

Java并发编程:volatile关键字解析:https://www.cnblogs.com/dolphin0520/p/3920373.html

存储器 - 缓存一致性 MESI 协议:如何让多核CPU的高速缓存保持一致:https://www.cnblogs.com/binarylei/p/12590759.html

java:volatile关键字原理的更多相关文章

  1. Java volatile 关键字底层实现原理解析

    本文转载自Java volatile 关键字底层实现原理解析 导语 在Java多线程并发编程中,volatile关键词扮演着重要角色,它是轻量级的synchronized,在多处理器开发中保证了共享变 ...

  2. [Java并发编程(三)] Java volatile 关键字介绍

    [Java并发编程(三)] Java volatile 关键字介绍 摘要 Java volatile 关键字是用来标记 Java 变量,并表示变量 "存储于主内存中" .更准确的说 ...

  3. 13、Java并发性和多线程-Java Volatile关键字

    以下内容转自http://tutorials.jenkov.com/java-concurrency/volatile.html(使用谷歌翻译): Java volatile关键字用于将Java变量标 ...

  4. Java Volatile关键字(转)

    出处:  Java Volatile关键字 Java的volatile关键字用于标记一个变量“应当存储在主存”.更确切地说,每次读取volatile变量,都应该从主存读取,而不是从CPU缓存读取.每次 ...

  5. Java volatile关键字详解

    Java volatile关键字详解 volatile是java中的一个关键字,用于修饰变量.被此关键修饰的变量可以禁止对此变量操作的指令进行重排,还有保持内存的可见性. 简言之它的作用就是: 禁止指 ...

  6. Java volatile关键字实现原理

    场景引入 可见性问题 先来看一张图: 上面的图,是简化版的Java内存模型,一个线程有自己的工作内存,同时还有一个共享的主内存. 线程1和线程2读取数据data时,先从主内存里加载data变量的值到工 ...

  7. 从根源上解析 Java volatile 关键字的实现

    1.解析概览 内存模型的相关概念 并发编程中的三个概念 Java内存模型 深入剖析Volatile关键字 使用volatile关键字的场景 2.内存模型的相关概念 缓存一致性问题.通常称这种被多个线程 ...

  8. java volatile 关键字(转)

    volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以 ...

  9. Java Volatile关键字

    在当前的Java内存模型下,线程可以把变量保存在本地内存(比如机器的寄存器)中,而不是直接在主存中进行读写. 这就可能造成一个线程在主存中修改了一个变量的值,而另外一个线程还继续使用它在寄存器中的变量 ...

随机推荐

  1. 深度强化学习中稀疏奖励问题Sparse Reward

    Sparse Reward 推荐资料 <深度强化学习中稀疏奖励问题研究综述>1 李宏毅深度强化学习Sparse Reward4 ​ 强化学习算法在被引入深度神经网络后,对大量样本的需求更加 ...

  2. 大数据学习(20)—— Zookeeper介绍

    ZooKeeper是什么 就像相声大师冯巩每次出场都说:"亲爱的观众朋友们,我想死你们啦"一样,我再强调一次,学习大数据官网很重要.Zookeeper官网看这里ZooKeeper ...

  3. 快速上手 Rook,入门云原生存储编排

    Rook 是一个开源 cloud-native storage orchestrator(云原生存储编排器),为各种存储解决方案提供平台.框架和支持,以与云原生环境进行原生集成. Rook 将存储软件 ...

  4. Netty 源码分析系列(二)Netty 架构设计

    前言 上一篇文章,我们对 Netty做了一个基本的概述,知道什么是Netty以及Netty的简单应用. Netty 源码分析系列(一)Netty 概述 本篇文章我们就来说说Netty的架构设计,解密高 ...

  5. JIT in MegEngine

    作者:王彪 | 旷视框架部异构计算组工程师 一.背景 什么是天元 旷视天元(MegEngine)是一个深度学习框架,它主要包含训练和推理两方面内容.训练侧一般使用 Python 搭建网络:而推理侧考虑 ...

  6. 自学linux——11.shell入门

    shell 基础 1.shell介绍(内置脚本) 程序开发的效率非常高,依赖于功能强大的命令可以迅速地完成开发任务(批处理) 语法简单,代码写起来比较轻松,简单易学 (1)什么是shell shell ...

  7. AlarmManager定时提醒的那些坑

    https://blog.csdn.net/zackratos/article/details/53243595 https://blog.csdn.net/bingshushu/article/de ...

  8. Build Puppet Clusters with Vagrant

    $ cd ~/docs/propuppetex/chapter3 $ cat Vagrantfile Vagrant.configure(VAGRANTFILE_API_VERSION) do |co ...

  9. Python语言系列-06-面向对象1

    楔子 #!/usr/bin/env python3 # author:Alnk(李成果) # 人狗大战例子引入面向对象 # 版本1 def hero(name, sex, hp, ce, level= ...

  10. noip15

    童话故事专场 T1 首先,dead line 是一条直线,而不是线段.考试的时候一直以为是线段,那么横竖共有n+m条,考虑斜着的,斜着的交点为有穷的,则需要满足斜率不同,那么只需要统计一边的,再乘2就 ...