java中,volatile关键字有两大作用:

  1.保证线程的可见性

  2.防止指令重排序

这篇文章主要通过典型案例,体现可见性这一特性。

概念:

  java中,堆内存是线程共享的。而每个线程,都应该有自己独享的内存用于工作。所以,当线程访问到堆内存中的共享变量时,会考虑copy一份,存在自己的工作空间中。之后对工作空间中的值进行操作,完成后重新写回到堆内存。

  这样一来,在多线程同时访问这个变量时,就可能出现拿不到实时的值的问题(根本原因在于:本来共享的变量,因为缓存到各个线程的工作空间导致数据在写回之前不互通)。

  而volatile的作用之一,就是解决这一问题。

下面通过一段代码,来展示volatile的这一特性。

 public class HelloVolatile {
private volatile boolean running = true; //开关,表示是否可运行 void m(){
System.out.println("m start");
//一直执行
while(running){ }
//如果running一直未true,下面的代码执行不到
System.out.println("m end");
} public static void main(String[] args) {
HelloVolatile helloVolatile = new HelloVolatile();
//新建线程,run方法调用m方法,running为true时一直循环
new Thread(helloVolatile::m, "非主线程").start();
//休眠1s
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
//主线程设置running为false,如果running不加volatile,则新建的线程是读不到的
helloVolatile.running = false;
}
}

running变量不加volatile的执行结果:

m start

加了volatile的执行结果:

m start
m end

可见性的原理:

MESI(缓存一致性)协议:

  1.写数据时,如果发现操作的是共享变量,会发出信号通知其他CPU设置该变量的缓存行为无效状态。

  2.当其他CPU使用这个变量时,会先去观察是否有更改的信号,当发现缓存行失效时,会从主内存(堆中)重新读取此变量。
volatile的优缺点:

  优点:高效(非锁机制)

  缺点:仅仅保证可见性,不保证数据的一致性。

Volatile关键字回顾之线程可见性的更多相关文章

  1. Volatile 关键字 内存可见性

    1.问题引入 实现线程: public class ThreadDemo implements Runnable { private boolean flag = false; @Override p ...

  2. 全面理解Java内存模型(JMM)及volatile关键字(转载)

    关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java类加载器(ClassLoad ...

  3. 全面理解Java内存模型(JMM)及volatile关键字

    [版权申明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/72772461 出自[zejian ...

  4. 并发之volatile关键字

    volatile关键字 volatile关键字是什么 在上一章我们讲到了并发的的三个概念,那么今天在讲解下在java中可以保证可见性和有序性的一个关键字. volatile关键字 :当变量的值被该关键 ...

  5. Java多线程编程——volatile关键字

    (本篇主要内容摘自<Java多线程编程核心技术>) volatile关键字的主要作用是保证线程之间变量的可见性. package com.func; public class RunThr ...

  6. 全面理解Java内存模型(JMM)及volatile关键字(转)

    原文地址:全面理解Java内存模型(JMM)及volatile关键字 关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型( ...

  7. 双重检查锁单例模式为什么要用volatile关键字?

    前言 从Java内存模型出发,结合并发编程中的原子性.可见性.有序性三个角度分析volatile所起的作用,并从汇编角度大致说了volatile的原理,说明了该关键字的应用场景:在这补充一点,分析下v ...

  8. 浅析Volatile关键字

    浅析Volatile关键字 在java中线程并发中,线程之间通信方式分为两种:共享内存和消息传递.共享内存指的是多个线程之间共享内存的属性状态:消息传递指的是线程之间发送信息来通信.在介绍volati ...

  9. Java volatile关键字实现原理

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

随机推荐

  1. js编写trim()函数

    1.js中本身是没有trim函数的,不过你可以自己写一个 function trim(str) {     var newStr = str.replace(/^\s*$/g,'')     retr ...

  2. __filename意思

    __filename 表示当前正在执行的脚本的文件名.它将输出文件所在位置的绝对路径,且和命令行参数所指定的文件名不一定相同. 如果在模块中,返回的值是模块文件的路径.

  3. Java 去掉字符串中的重复数据

    有一组字符串比如 北京,北京,上海,上海,上海,武汉-------->要得到        北京,上海,武汉 怎么去掉里面重复的字符串? function DelRepetStr(String ...

  4. git 学习 3

    远程仓库 添加远程库 GitHub 注册账号并建立 repository,Clone with SSH 1 $ ssh-keygen -t rsa -C "youremail@example ...

  5. 《Java 8实战》读书笔记系列——第三部分:高效Java 8编程(四):使用新的日期时间API

    https://www.lilu.org.cn/https://www.lilu.org.cn/ 第十二章:新的日期时间API 在Java 8之前,我们常用的日期时间API是java.util.Dat ...

  6. C++走向远洋——50(Time类中的运算符重载、一目,二目比较运算符、二目赋值运算符、二目加减法运算符)

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...

  7. git指令-管理修改

    git指令-管理修改 git管理的不是文件,而是修改 eg:对readme.txt文件进行修改一行 在最后追加一句git has to tracked 然后添加,并且查看状态 cat +文件名称 表示 ...

  8. Java并发编程(01):线程的创建方式,状态周期管理

    本文源码:GitHub·点这里 || GitEE·点这里 一.并发编程简介 1.基础概念 程序 与计算机系统操作有关的计算机程序.规程.规则,以及可能有的文件.文档及数据. 进程 进程是计算机中的程序 ...

  9. volatile和synchronized到底啥区别?多图文讲解告诉你

    你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it well enough ...

  10. Asp.Net Core Endpoint 终结点路由之中间件应用

    一.概述 这篇文章主要分享Endpoint 终结点路由的中间件的应用场景及实践案例,不讲述其工作原理,如果需要了解工作原理的同学, 可以点击查看以下两篇解读文章: Asp.Net Core EndPo ...