Java并发——volatile关键字
什么是内存可见性?
这里就要提一下JMM(Java内存模型)。当线程在运行的时候,并不是直接直接修改电脑主内存中的变量的值。线程间通讯也不是直接把一个线程的变量的值传给另一个线程,让其刷新变量。下面是一副抽象的结构图。
线程A要想和线程B通信,其实是通过改变主内存中的共享变量的值。具体的工作原理就是,线程A不能直接修改主内存中的值,而是在主内存和线程A中需要一个缓存区(每个线程都有自己的一个缓冲区),再将共享变量的副本拷入缓冲区,在缓冲区里修改完之后再通过一些指令将副本改变的值刷新进主内存。这里刷新就会出现很多问题,有可能线程A修改了共享变量的值没有刷新进去,当B需要使用共享变量的时候就会用旧值。所以这就是多线程存在一个比较大的问题。前面介绍的synchronized关键字,以及现在介绍的volatile,后面会介绍的CAS,其实都会解决这个内存可见性的问题。不过实现原理不同。要保证内存可见性也就是每一个线程修改一次共享变量的值,都需要让主内存中的变量刷新,并且让其他线程也刷新共享变量副本。
volatile如何实现内存可见性?
其实volatile的可见性底层原理主要是内存屏障和禁止重排序。内存屏障是在volatile变量读操作之前加入load指令,从主内存中读取最新的共享变量,而不是使用之前的副本值,同样写的时候也是加入store指令,将本地内存中的共享变量值强制刷新到主内存中。这样就保证了每个线程拿到的volatile变量是最新的值。下面是两个示意图
StoreStore屏障:对于这样的语句Store1; StoreStore; Store2,在Store2及后续写入操作执行前,保证Store1的写入操作对其它处理器可见。
StoreLoad屏障:对于这样的语句Store1; StoreLoad; Load2,在Load2及后续所有读取操作执行前,保证Store1的写入对所有处理器可见。它的开销是四种屏障中最大的。在大多数处理器的实现中,这个屏障是个万能屏障,兼具其它三种内存屏障的功能
LoadLoad屏障:对于这样的语句Load1; LoadLoad; Load2,在Load2及后续读取操作要读取的数据被访问前,保证Load1要读取的数据被读取完毕。也就是
LoadStore屏障:对于这样的语句Load1; LoadStore; Store2,在Store2及后续写入操作被刷出前,保证Load1要读取的数据被读取完毕。
上面四个屏障不但会强制变量刷新,而且会防止指令之间的重排序(JVM对于没有数据依赖关系的指令会进行重排序,指令重排序也会导致变量的值读取是错误的)。volatile的底层就是这样实现,较synchronized更为轻量级,毕竟synchronized是用来修饰方法和代码块的,而volatile保证的只是一个变量,所以更为轻量级。
如何优化volatile关键字?
我们先来弄清楚对于英特尔酷睿i7、酷睿、Atom和 NetBurst,以及Core Solo和Pentium M处理器的L1、L2或L3缓存的高速缓存行是64个字节宽,不支持部分填充缓存行。要想优化volatile变量运行速度,只需要将变量追加到64个字节
也就是如果一个volatile变量存入高速缓存且不足64个字节长度,这时候可能在同一个缓存行中就会再存入另一个volatile变量,而由于缓存一致性机制,当处理第一个volatile变量的时候,整个缓存行是锁定的,这时候第二个volatile变量或者缓存行其他变量需要被其他处理器操作就必须等到第一个volatile变量操作完才能进行。如果这时volatile变量是64个字节独占一个缓存行的时候,那么就不会有上面的影响发生。
那么什么时候我们都需要追加64个字节吗?有下面两种情况不需要追加
1、缓存行非64字节宽的处理器。如P6系列和奔腾处理器,它们的L1和L2高速缓存行是32个字节宽。
2、共享变量不被频繁地写。可以看出追加字节的方式是需要性能消耗的,如果共享变量不被频繁地写的话,锁定的概率小,不需要追加字节。
总结
volatile是修饰变量的一个关键字,写在基本数据类型之前。用来保证这个变量在多线程的环境下具有可见性。是通过内存屏障和禁止指令重排序来实现的,但是不具有原子性。CAS和synchronized才会保证原子性。
Java并发——volatile关键字的更多相关文章
- Java 并发 —— volatile 关键字
volatile 修饰变量等于向编译器传达如下两层含义: 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的. 禁止进行指令重排序. volat ...
- Java并发--volatile关键字
一.volatile的实现原理 synchronized是阻塞式同步,在线程竞争激烈的情况下会升级为重量级锁,而volatile就可以说是JVM提供的最轻量级的同步机制.JMM告诉我们,各个线程会将共 ...
- Java并发——volatile关键字的使用
volatile关键字的使用volatile关键字原理适合使用volatile关键字的情况当且仅当满足以下所有条件时,才==应该==使用volatile关键字:volatile关键字的作用volati ...
- 【转】java中volatile关键字的含义
java中volatile关键字的含义 在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言 ...
- 转:java中volatile关键字的含义
转:java中volatile关键字的含义 在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言 ...
- java 并发——volatile
java 并发--volatile 介绍 维基百科: volatile 是一个类型修饰符(type specifier).volatile 的作用是确保本条指令不会因编译器的优化而省略,且要求每次直接 ...
- Java并发-volatile的原理及用法
Java并发-volatile的原理及用法 volatile属性:可见性.保证有序性.不保证原子性.一.volatile可见性 在Java的内存中所有的变量都存在主内存中,每个线程有单独CPU缓存内存 ...
- Java并发——volatile的原理
111 Java并发——volatile的原理
- Java中Volatile关键字详解 (转自郑州的文武)
java中volatile关键字的含义:http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html 一.基本概念 先补充一下概念:J ...
随机推荐
- NOIP2017Day1题解
Day1 T1.小学奥数... 代码: #include<iostream> #include<cstring> #include<string> #include ...
- 高通spi 屏幕 -lk代码分析
lk SPI驱动 1. 初始化时钟 在lk中,我们是从kmain开始执行下来的,而执行顺序则是先初始化时钟,也就是在platform_early_init函数中开始执行的: 在这里我们需要修改这个函数 ...
- 在C++98基础上学习C++11新特性
自己一直用的是C++98规范来编程,对于C++11只闻其名却没用过其特性.近期因为工作的需要,需要掌握C++11的一些特性,所以查阅了一些C++11资料.因为自己有C++98的基础,所以从C++98过 ...
- .NET之IOC控制反转运用
当前场景: 如果有不同的用户.使用同一个系统.而不同的客户有某些不同的需求.在不改变系统主体的情况下,可以直接使用IOC控制反转依赖搭建项目 1.添加接口层 目前里面只有一个会员的类.里面有一个登录接 ...
- 原生aspx页面如何引用公共js和css
项目过程中遇到一个问题,每个页面需要引用很多的js和css文件,其中很多都是控件,而且大部分都是一样的,造成很多重复引用. 针对这种情况,参考了mvc的BundleConfig,思路是建立一个公用的用 ...
- linux中普通的文件查看操作(cat、more、less、head、tail)
cat:基本是最常用的查看文件内容的linux命令. more 也是用来查看一个文件的内容.当文件内容太多,一屏幕不能占下,而你用cat肯定是看不前面的内容的,那么使用more就可以解决这个问题了.当 ...
- 关于java多线程关键字volatile的理解
volatile关键字的作用是强制从公共堆栈中取得变量的值,而不是从线程私有数据栈中取得变量的值. 使用volition关键字增加了实例变量在多个线程间的可见性.但volition有个致命的缺点就是不 ...
- 初识Java NIO
原文链接:http://tutorials.jenkov.com/java-nio/index.html Java NIO是java 1.4之后新出的一套IO接口,这里的新是相对于原有标准的Java ...
- Python高级教程
关键字is 和 == 的区别 a = 'hello world' b = 'hello world' a == b #返回True a is b #返回False 注意:is 判断是否是一个ID, = ...
- Linux时间子系统之(六):POSIX timer
专题文档汇总目录 Notes:首先讲解了POSIX timer的标识(唯一识别).POSIX Timer的组织(管理POSIX Timer).内核中如何抽象POSIX Timer:然后分析了POSIX ...