Volatile关键字总结
来源:互联网 发布:微信载入数据失败 编辑:程序博客网 时间:2024/05/17 21:49
一、Volatile关键字的知识点
- volatile能保证线程的可见性,但不能保证线程的原子性
- 通过volatile关键字,保证线程每次读取变量是从主存中读取,不是通过L3或者L4缓存中读取
- 但问题在于volatile关键字只能保证每次缓存失效,不能保证操作是原子性的,我们知道i++这样的操作是分为3个步骤
- 从内存中读取变量
- 在线程的栈桢中操作加1
- 讲结果写入内存中
- 这样在多个线程中存在这样的现象,i=10,线程1读取了i的最新变量值,但是此时线程1遭遇阻塞或者挂起,线程2此时区读取i的最新变量值,此时仍为10,那么线程1和线程2都进行1++操作,那么操作了2次i++,结果为11
以下为代码实例
package com.huyi.thread;import java.util.Iterator;import java.util.LinkedList;import java.util.List;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * Created with IntelliJ IDEA. * * @Author: huyi * @Date: 2017/11/28 19:48 */public class Test { public volatile int inc = 0; Lock lock = new ReentrantLock(); public void increase() { lock.lock(); try { inc++; }finally { lock.unlock(); } } public static void main(String[] args) { final Test test = new Test(); for(int i=0;i<10;i++){ new Thread(){ public void run() { for(int j=0;j<1000;j++) test.increase(); }; }.start(); } while(Thread.activeCount()>1) //保证前面的线程都执行完 Thread.yield(); System.out.println(test.inc); }}
可以发现结果(请断点执行)不为10000
二、volatile关键字的使用场景
下面这段话摘自《深入理解Java虚拟机》:
“观察加入volatile关键字和没有加入volatile关键字时所生成的汇编代码发现,加入volatile关键字时,会多出一个lock前缀指令”
lock前缀指令实际上相当于一个内存屏障(也成内存栅栏),内存屏障会提供3个功能:
1)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;
2)它会强制将对缓存的修改操作立即写入主存;
3)如果是写操作,它会导致其他CPU中对应的缓存行无效。
- volatile能保证可见性以及有序性,通过这些特性我们可以使用:
context = new Context(); //语句1boolean volatile flag = true; //语句2while(!flag){ //语句3 sleep();}doSomeThing(context); //语句4
假设线程1执行到语句2,线程2执行到语句3,由于flag使用了volatile关键字,那么能够保证语句1在语句2前执行,那么线程2执行到语句4的时候context是已经实例化,不会抛出NullPointException
- 使用双重检查 double-check
public class Singleton { private volatile Singleton singleton; public static Singleton getSingleton(){ if(singleton == null){ synchronized(this){ if(singleton == null){ singleton = new Singleton(); } } } return singleton; }}
可能觉得这段代码很奇怪,为什么要检查2次singleton是否为空,实际上如果我们要写单例模式的话,应该会这样
public class Singleton { private volatile Singleton singleton; public static synchronized Singleton getSingleton(){ if(singleton == null){ singleton = new Singleton(); } return singleton; }}
这样会简单很多,但反过来想想,第一段代码检查2次不是会更好减少线程锁(monitor)的开销吗,如果存在大量的线程操作,如何减少线程开销也是要考虑的问题
参考资料:
1. https://www.cnblogs.com/dolphin0520/p/3920373.html
2. http://blog.csdn.net/dl88250/article/details/5439024
阅读全文
0 0
- volatile关键字用法总结
- java volatile关键字总结
- volatile关键字总结
- volatile关键字学习总结
- volatile关键字总结
- Volatile关键字总结
- 学习笔记:volatile关键字总结
- C/C++ volatile关键字用法总结
- Static、Extern、Volatile及Const关键字总结
- Static、Extern、Volatile及Const关键字总结
- Static、Extern、Volatile及Const关键字总结
- [总结]C++关键字详解——volatile
- 并发编程总结之volatile关键字
- volatile关键字
- 关键字volatile
- volatile关键字
- volatile关键字
- volatile关键字
- css3 中transition监听事件
- Python 爬虫项目示例
- Sublime Text3如何解决乱码
- 产品经理之互联网产品流程设计
- Closure
- Volatile关键字总结
- 《弃子长安》第十章 血染胡杨
- Maven学习总结系列二:Maven的安装和配置
- 洛谷P2633 Count on a tree
- Linux基础指令学习01
- 191. Number of 1 Bits
- 做市商业务是个啥
- Approaching (Almost) Any Machine Learning Problem | Abhishek Thakur—翻译
- Decorator