java volatile
volatile可以保证变量的可见性
当一个变量定义为volatile后,此变量对所有的线程具有可见性。这里的可见性是指当一个线程修改了这个变量的值,新值对于其他线程来说是可以立即得知的。
每次使用volatile变量前都必须先从主内存刷新最新的值,这保证能看见其他线程对变量所做的修改后的值。每次修改volatile变量后都必须同步回主内存,这保证其他线程可以看到自己对变量所做的修改。正是这两条规则保证了volatile变量的可见性。
volatile要求线程每次从共享内存中读取变量,而不是私有内存中读取。
volatile可以保证有序性
volatile可以禁止指令重排序优化,重排序是指编译器和处理器为了优化程序性能而对指令序列进行排序的一种手段。但是重排序也需要遵守一定规则,重排序操作不会对存在数据依赖关系的操作进行重排序。比如:a=1;b=a; 这个指令序列,由于第二个操作依赖于第一个操作,所以在编译时和处理器运行时这两个操作不会被重排序。但是在多线程环境下,可能出现问题。如下示例:
Map configOptions;
volatile boolean initialized = false; // 以下代码在线程A中执行
// 线程A完成配置信息后,initialized改为true
configOptions = new HashMap();
processConfigOptions(configOptions);
initialized = true; // 以下代码在线程B中执行
// 等待initialized为true,表示线程A已完成配置
while (!initialized) {
sleep();
}
// 线程A完成配置后,线程B可以开始doSomething();
doSomething();
initialized必须定义为volatile,否则可能出现线程A先赋值initialized为true,而后执行配置。
volatile保证了在赋值initialized之前,先执行完其前面的代码。
volatile 性能
volatile 的读性能消耗与普通变量几乎相同,但是写操作稍慢,因为它需要在本地代码中插入许多内存屏障指令来保证处理器不发生乱序执行。
volatile在并发下运算是不安全的,不能保证原子性
如下示例,20个线程分别将变量race自加100次,运算结果race的值小于20000 。
public class VolatileTest {
public static volatile int race;
public static void increase() {
race++;
}
private static final int threads_count = 20;
public static void main(String[] args) {
Thread[] threads = new Thread[threads_count];
for (int i=0; i<threads_count; i++) {
threads[i] = new Thread(
new Runnable() {
@Override
public void run() {
for (int i=0; i<100; i++) increase();
}
}
);
threads[i].start();
}
System.out.println(race);
}
}
示例中,race++不是一个原子操作,其步骤分解如下:
1)从内存中取出race的值;
2)计算race的新值(加1);
3)将race的值写入内存中。
race是volatile修饰的,这保证了其可见性,即所有的线程在使用该变量时,都是从共享内存中读取。
但volatile不保证原子性,一个线程在进行第二步操作时,其它线程可以读取或修改race的值,这就出现了不同步的现象。
所谓原子性,是指一个操作或多个操作要么全部执行完成且执行过程不被中断,要么就不执行。例如,若race++是原子性的,某个线程在执行该操作时,其他线程不能干涉,必须等待其执行完毕。
java volatile的更多相关文章
- java volatile的一个验证反例(转)
网上关于java volatile的资料已经不少了,但搜了好久也没看到谁用代码很好地验证过使不使用volatile的差异.最近自己写了个测试,意外的看到了两者的明显区别,为什么说意外呢,因为根据我的测 ...
- [Java并发编程(五)] Java volatile 的实现原理
[Java并发编程(五)] Java volatile 的实现原理 简介 在多线程并发编程中 synchronized 和 volatile 都扮演着重要的角色,volatile 是轻量级的 sync ...
- [Java并发编程(四)] Java volatile 的理论实践
[Java并发编程(四)] Java volatile 的理论实践 摘要 Java 语言中的 volatile 变量可以被看作是一种 "程度较轻的 synchronized":与 ...
- [Java并发编程(三)] Java volatile 关键字介绍
[Java并发编程(三)] Java volatile 关键字介绍 摘要 Java volatile 关键字是用来标记 Java 变量,并表示变量 "存储于主内存中" .更准确的说 ...
- 13、Java并发性和多线程-Java Volatile关键字
以下内容转自http://tutorials.jenkov.com/java-concurrency/volatile.html(使用谷歌翻译): Java volatile关键字用于将Java变量标 ...
- Java Volatile关键字(转)
出处: Java Volatile关键字 Java的volatile关键字用于标记一个变量“应当存储在主存”.更确切地说,每次读取volatile变量,都应该从主存读取,而不是从CPU缓存读取.每次 ...
- Java volatile 关键字底层实现原理解析
本文转载自Java volatile 关键字底层实现原理解析 导语 在Java多线程并发编程中,volatile关键词扮演着重要角色,它是轻量级的synchronized,在多处理器开发中保证了共享变 ...
- Java volatile关键字详解
Java volatile关键字详解 volatile是java中的一个关键字,用于修饰变量.被此关键修饰的变量可以禁止对此变量操作的指令进行重排,还有保持内存的可见性. 简言之它的作用就是: 禁止指 ...
- Java volatile的用法---转载
我们知道,在Java中设置变量值的操作,除了long和double类型的变量外都是原子操作,也就是说,对于变量值的简单读写操作没有必要进行同步. 这在JVM 1.2之前,Java的内存模型实现总是从主 ...
- JAVA volatile 关键字
一.volatile(易变的) Java 语言提供了一种稍弱的同步机制,即volatile修饰变量.用来确保将变量的更新操作通知到其他线程,保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新 ...
随机推荐
- week7 ls
week7 ls 实现ls: 实现ls -l:
- django之admin管理工具
admin组件 admin是django提供的基于web的管理工具 >如何使用: 1.激活管理工具 通常会在生成项目时在urls.py中自动设置好 from django.urls import ...
- laravel进行单元测试的时候如何模拟数据库以及mockery的调用
单元测试是独立的,所谓的独立是指有独立的运行容器,独立的数据库. 这样做有什么好处呢? (1). 不会跟正常的容器产生冲突,继而影响正常业务. (2). 数据库独立防止数据被修改影响单元测试结果. 这 ...
- .net代码修改webconfig
/// <summary> /// 写入web.config /// </summary> /// <param name="item">app ...
- 数据结构与算法之PHP排序算法(快速排序)
一.基本思想 快速排序又称划分交换排序,是对冒泡排序的一种改进,亦是分而治之思想在排序算法上的典型应用. 它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部 ...
- JAVA的原子性和可见性,线程同步的理解
1.原子性 (1)原子是构成物质的基本单位(当然电子等暂且不论),所以原子的意思代表着——“不可分”: (2)原子性是拒绝多线程操作的,不论是多核还是单核,具有原子性的量,同一时刻只能有一个线程来对它 ...
- 模糊测试(fuzzing)是什么
一.说明 大学时两个涉及“模糊”的概念自己感觉很模糊.一个是学数据库出现的“模糊查询”,后来逐渐明白是指sql的like语句:另一个是学专业课时出现的“模糊测试”. 概念是懂的,不外乎是“模糊测试是一 ...
- VS2017调试技巧
Visual Studio的调试技巧 调试技巧是衡量程序员水平的一个重要指标.掌握好的调试技巧与工具的使用方法,也是非常重要的.*** 演示环境: VS2017C#*** 演示用的代码: publ ...
- 走进JavaScript
JavaScript的作用:操作HTML元素,响应用户的操作,处理数据: script标签的type或者language可以写也可以不写: script标签防止位置:head结束之前或者body结束之 ...
- linux基本网络配置
-- linux基本网络配置管理 rhel6开始有一个networkmanger的网络配置服务(可以图形配置网络,拔号,无线连接,vpn等)但此服务开启会造成你的ip不固定(会dhcp获取),而且后期 ...