java中volatile的含义_java中volatile关键字的含义
(支持原创)本篇文章非原创,原文章地址:
http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html
在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉。
Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和 volatile 关键字机制。
synchronized
同步块大家都比较熟悉,通过 synchronized 关键字来实现,所有加上synchronized 和 块语句,在多线程访问的时候,同一时刻只能有一个线程能够用
synchronized 修饰的方法 或者 代码块。
volatile
用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最的值。volatile很容易被误用,用来进行原子性操作。
下面看一个例子,我们实现一个计数器,每次线程启动的时候,会调用计数器inc方法,对计数器进行加一
执行环境——jdk版本:jdk1.6.0_31 ,内存 :3G cpu:x86 2.4G
public classCounter {public static int count = 0;public static voidinc() {//这里延迟1毫秒,使得结果明显
try{
Thread.sleep(1);
}catch(InterruptedException e) {
}
count++;
}public static voidmain(String[] args) {//同时启动1000个线程,去进行i++计算,看看实际结果
for (int i = 0; i < 1000; i++) {new Thread(newRunnable() {
@Overridepublic voidrun() {
Counter.inc();
}
}).start();
}//这里每次运行的值都有可能不同,可能为1000
System.out.println("运行结果:Counter.count=" +Counter.count);
}
}运行结果:Counter.count=995
实际运算结果每次可能都不一样,本机的结果为:运行结果:Counter.count=995,可以看出,在多线程的环境下,Counter.count并没有期望结果是1000
很多人以为,这个是多线程并发问题,只需要在变量count之前加上volatile就可以避免这个问题,那我们在修改代码看看,看看结果是不是符合我们的期望
public classCounter {public volatile static int count = 0;public static voidinc() {//这里延迟1毫秒,使得结果明显
try{
Thread.sleep(1);
}catch(InterruptedException e) {
}
count++;
}public static voidmain(String[] args) {//同时启动1000个线程,去进行i++计算,看看实际结果
for (int i = 0; i < 1000; i++) {new Thread(newRunnable() {
@Overridepublic voidrun() {
Counter.inc();
}
}).start();
}//这里每次运行的值都有可能不同,可能为1000
System.out.println("运行结果:Counter.count=" +Counter.count);
}
}
运行结果:Counter.count=992
运行结果还是没有我们期望的1000,下面我们分析一下原因
在 java 垃圾回收整理一文中,描述了jvm运行时刻内存的分配。其中有一个内存区域是jvm虚拟机栈,每一个线程运行时都有一个线程栈,
线程栈保存了线程运行时候变量值信息。当线程访问某一个对象时候值的时候,首先通过对象的引用找到对应在堆内存的变量的值,然后把堆内存
变量的具体值load到线程本地内存中,建立一个变量副本,之后线程就不再和对象在堆内存变量值有任何关系,而是直接修改副本变量的值,
在修改完之后的某一个时刻(线程退出之前),自动把线程变量副本的值回写到对象在堆中变量。这样在堆中的对象的值就产生变化了。下面一幅图
描述这写交互
read and load 从主存复制变量到当前工作内存
use and assign 执行代码,改变共享变量值
store and write 用工作内存数据刷新主存相关内容
其中use and assign 可以多次出现
但是这一些操作并不是原子性,也就是 在read load之后,如果主内存count变量发生修改之后,线程工作内存中的值由于已经加载,不会产生对应的变化,所以计算出来的结果会和预期不一样
对于volatile修饰的变量,jvm虚拟机只是保证从主内存加载到线程工作内存的值是最新的
例如假如线程1,线程2 在进行read,load 操作中,发现主内存中count的值都是5,那么都会加载这个最新的值
在线程1堆count进行修改之后,会write到主内存中,主内存中的count变量就会变为6
线程2由于已经进行read,load操作,在进行运算之后,也会更新主内存count的变量值为6
导致两个线程及时用volatile关键字修改之后,还是会存在并发的情况。
java中volatile的含义_java中volatile关键字的含义相关推荐
- java中volatile关键字的含义_java中volatile关键字的含义
转自:http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html 在java线程并发处理中,有一个关键字volatile的使用目前存 ...
- java中volatile关键字的含义_Java里volatile关键字是什么意思
在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言是支持多线程的,为了解决线程并发的问题,在语 ...
- java volatile 基本类型_Java中Volatile关键字详解(转)
一.基本概念 先补充一下概念:Java 内存模型中的可见性.原子性和有序性. 可见性: 可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉.通常,我们无法确保执行读操作的线程能适时地看到其 ...
- java i 线程不安全_java中的++i是线程安全的吗?
java中的++i是线程安全的吗?为什么?怎么使它线程安全呢? 先说答案: 非线程安全 先说下为什么是非线程安全的? 从Java内存模型说起 Java内存模型规定了所有的便利都存储在主内存中,每个线程 ...
- java对于数组的定义_Java中方法的定义与使用,以及对数组的初步了解。
方法 方法的含义 定义: 方法就是用来完成解决某件事情或实现某个功能的办法. 方法实现的过程中,会包含很多条语句用于完成某些有意义的功能--通常是处理文本,控制输入或计算数值. 我们可以通过在程序代码 ...
- java类怎么删除对象_java中对象的生成使用和删除
请教大神,在java里,对象生成后,如何删除对象呢?请教大神,在java里,对象生成后,如何删除对象呢? 对象状态由JVM自动管理,GC线程自动回收无用对象,无需也不能自己删除对象. 请问在JAVA中 ...
- java的布局管理器_Java中提供了几种布局管理器
近日,很多网友都在关注Java中提供了几种布局管理器这个话题,那么Java中提供了几种布局管理器具体情况是怎么样的呢?Java中提供了几种布局管理器的相关信息有哪些?下面的内容是小编为大家找到的关于J ...
- java中组件与容器_java中的容器组件和非容器组件
1.java使用到的图形类主要在java.awt 与javax.swing包中. 2.java.awt 与 javax.swing包的区别: ① java.awt中使用的图形类都是依赖于系统的图形库的 ...
- java boolean几个字节_Java中boolean类型到底占用多少个字节?
1.时间:2017-07-03 07:37:06YuanMxy 2.问题描述:今天在复习java基础的时候发现一小问题,Java中boolean类型到底占用多少个字节? 3.问题解答: (1)什么是b ...
最新文章
- winform groupbox控件放到窗体中间位置
- 大地发生了变化写具体_小学语文三年级下册期末检测卷 (2)
- layui的登录ajax,layui如何实现登录功能
- 如何优雅的升级内核?
- 【华为云动态】华为云携手Google,IBM,SAP等多家知名企业加入CDF,助力软件开发生态发展
- 树莓派该文件名_树莓派的20个常用命令
- 指针和引用的相同与不同
- 学习小实例--滚动条
- 五、实现一个10秒钟的倒计时,即:从10~0依次打印,每次打印间隔一秒
- 雷达的L、S、C、X波段是什么
- build lavas 失败_基础教程 - 快速开始 PWA 工程 - 《Lavas 指导教程文档》 - 书栈网 · BookStack...
- matlab数值计算习题解析,第3章MATLAB数值计算-习题
- 迅捷fw325r虚拟服务器设置,Fast迅捷FW325R无线路由器设置
- 图像处理:语义分割(sematic segmentation)
- 7、机器视觉之色彩空间转换
- 20145325张梓靖 《网络对抗技术》 Web安全基础实践
- EasyExcel实现Excel文件导入导出功能
- MDT 2013 从入门到精通之Office 2013应答文件生成
- centos7下安装mycat2
- 使用接口实现翻译日语
热门文章
- linux 软硬文件类型,linux文件属性和类型、系统链接文件、软链接和硬链接
- 为什么开了数据不能上网_Doinb和LCK选手双排为什么不能开语音?Doinb深夜道出实情...
- VTK修炼之道66:体绘制裁剪_Cripping技术
- VTK修炼之道5_Procedural Source Object
- 深入理解文档/视图框架体系_九宫格项目开发感悟
- [计算机视觉:算法与应用]学习笔记一:图像形成
- Delphi中的Type
- win10电脑如何安装Openssh?开启Server服务?
- 程序员面试系列——冒泡排序
- spring security认证的底层实现