Java中的关键字--volatile
volatile关键字经常用来修饰变量。不过,volatile本身很容易被误用。本篇就介绍一下volatile的原理和使用方式。
在介绍volatile关键字原理前,我们首先要了解JVM运行时的内存分配逻辑。

对于成员变量i,它存储在堆内存中。每个线程在运行时都会有一个自己的线程栈,线程如果要访问类的成员变量i,会通过引用获取到堆中变量i实际的值10,然后把这个变量值拷贝到自己的栈内存中,作为一个变量副本,之后线程便不再会与堆中的变量有实际联系。每个线程都有一个自己的本地副本,相互隔离。线程访问自己栈内存的效率比访问堆的效率高。线程对变量i值的修改,只会修改自己线程副本中的值,修改结束后,在线程退出前,会把自己线程副本中的值,刷新到堆中。
保证内存可见性
对于如下代码:
public class VolatileTest implements Runnable{
//volatile
private static boolean flag = false;
@Override
public void run() {
while (!flag){
System.out.println(Thread.currentThread().getName() +"执行中");
}
System.out.println(Thread.currentThread().getName() +"执行完毕");
}
//main线程
public static void main(String[] args) throws InterruptedException {
new Thread(new VolatileTest(), "支线程Volatile").start();
Thread.sleep();
flag = true;
}
}
大多数时候可以正常中断,但是一旦发送异常,便会导致线程死循环。所以需要在flag标志上加一个volatile关键字。对于加了volatile关键字的变量值,线程1修改了这个值的话,会强制将修改值直接写入堆内存中,其他线程各自线程栈中的变量副本无效,只能去堆中取最新的变量值。多个线程之间的内存可见得以保证。
值得注意的是,volatile关键字不能保证原子性。
private volatile int i; i++;
i ++ 这个操作涉及到获取值,自增和赋值3部分。无法直接完成。上面想要以volatile来实现原子性的写法是错误的。
禁止指令重排
现代JVM对代码的执行顺序有一定的优化。例如:
int a = ;
int b = ;
int c = a + b;
上面3条指令进过JVM优化以后,时间的执行顺序不一定是从上到下,有可能是 第二条--->第一条-->第三条。总之不会影响最终执行结果。
但是在多线程情况下,如下代码就会有风险:
//线程1:
context = loadContext();
inited = true; //线程2:
while(!inited ){ }
doSomething(context);
线程1的两条语句之间没有依赖性,经过指令重排后,有可能inited置为true以后,context还没有初始化。线程2发现inited为true,以为初始化完成,结束循环,用时间还没有初始化的context去执行doSomething()方法。报错。所以我们可以用volatile关键字修饰inited,保证context初始化。
Java中的关键字--volatile的更多相关文章
- java中的关键字volatile
1.volatile简介 volatile作为java中的关键词之一,用以声明变量的值可能随时会被别的线程修改,使用volatile修饰的变量会强制将修改的值立即写入主存,主存中值的更新会使缓存中的值 ...
- java中synchronized关键字分析
今天我们来分析一下java中synchronized关键字.首先来看一段java代码:(本地编译环境为mac,jdk1.8的环境) Demo.java package com.example.spri ...
- Java 中的关键字
Java 中有多少个关键字,有大小写之分吗? Java 中有 48 个关键字在使用 + 两个保留关键字未使用,共 50 个关键字. Java 关键字全部都由是小写组成. Java 中保留关键字分别是哪 ...
- Java中的关键字有哪些?「Java中53个关键字的意义及使用方法」
Java中的关键字有哪些? 1)48个关键字:abstract.assert.boolean.break.byte.case.catch.char.class.continue.default.do. ...
- Java中的关键字 transient
先解释下Java中的对象序列化 在讨论transient之前,有必要先搞清楚Java中序列化的含义: Java中对象的序列化指的是将对象转换成以字节序列的形式来表示,这些字节序列包含了对象的数据和信息 ...
- Java中native关键字
Java中native关键字 标签: Java 2016-08-17 11:44 54551人阅读 评论(0) 顶(23453) 收藏(33546) 今日在hibernate源代码中遇到了nati ...
- Java复习笔记--java中this 关键字
Java中this关键字,this可以调用类的成员变量和成员方法,this还可以调用类中的构造方法.使用这种方式值得注意的是, 只可以在无参构造方法中的第一句使用this关键字调用有参构造方法. pu ...
- Java中this关键字的使用
本文介绍了在Java中this关键字的作用于使用方法 当局部变量和成员变量重名时,在方法中使用this时,表示的是该方法所在类中的成员变量.(this指的是当前对象自己) 如:public class ...
- Java中this关键字在构造方法中的使用
1. Java中this关键字代表对象本身.用this关键字可以在类的内部调用属性和方法,这样代码的可读性比较高,因为它明确的指出了这个属性或方法的来源. 2. 同时在构造函数中也可以使用this关键 ...
随机推荐
- uboot tag存储主要部分代码
https://www.cnblogs.com/pokerface/p/5217106.html cmd_bootm.c //传递给内核的参数 int do_bootm (cmd_t ...
- alert(1) to win 2
function escape(s) { s = s.replace(/"/g, '\\"'); return '<script>console.log("' ...
- 【串线篇】spring boot日志使用
一.默认配置 1.SpringBoot默认帮我们配置好了日志: //记录器 Logger logger = LoggerFactory.getLogger(getClass()); @Test pub ...
- SpringCLoud之搭建Zuul网关集群
1.使用技术 Springboot,SpringCloud,Zuul,Nignx 2.目的 使用Zuul搭建微服务高可用的网关 3.项目创建 3.1 创建注册中心(略) 3.2 创建一个hello-s ...
- layer.js插件
官方网址: http://layer.layui.com/
- C++ Map相同key是否覆盖问题分析
C++的标准库关联容器map是不允许有key相同的键值对存在的.那么当key已经存在的情况下,我们再次插入相同的key,那么key的value会被覆盖吗? 测试代码: 测试结果: 从测试结果我们可以得 ...
- python使用中遇到的一些问题
一./usr/bin/ld:cannot find -lxxx错误 例如出现了问题: /usr/bin/ld:cannot find -lssl 其中xxx表示函式库文件名称,如上面的libssl.s ...
- day33—前端开发的模块化和组件化
转行学开发,代码100天——2018-04-18 今天是记录前端开发中模块化.组件化的知识.关于何为模块化,何为组件化以及为何要如此,目前还是处于一个只可意会不可言传的理解应用阶段. 当然,这样的存在 ...
- CET-6 分频周计划生词筛选(Week 3)
点我阅读 Week 3 2016.09.11 p113 manipulate + propel p114 expedition + deficit p115 all p116 envisage p11 ...
- $_POST,$_GET,$_REQUEST区分
PHP $_REQUEST PHP $_REQUEST 用于收集 HTML 表单提交的数据. 下面的例子展示了一个包含输入字段及提交按钮的表单.当用户通过点击提交按钮来提交表单数据时, 表单数据将发送 ...