[.net 多线程]volatile 摘录
一、volatile介绍
volatile 关键字指示一个字段可以由多个同时执行的线程修改。 声明为 volatile 的字段不受编译器优化(假定由单个线程访问)的限制。 这样可以确保该字段在任何时间呈现的都是最新的值。
volatile 修饰符通常用于由多个线程访问但不使用 lock 语句对访问进行序列化的字段。
volatile 关键字可应用于以下类型的字段:
引用类型。
指针类型(在不安全的上下文中)。 请注意,虽然指针本身可以是可变的,但是它指向的对象不能是可变的。 换句话说,您无法声明“指向可变对象的指针”。
类型,如 sbyte、byte、short、ushort、int、uint、char、float 和 bool。
具有以下基类型之一的枚举类型:byte、sbyte、short、ushort、int 或 uint。
已知为引用类型的泛型类型参数。
可变关键字仅可应用于类或结构字段。 不能将局部变量声明为 volatile。
- 二、深入解析
比较一下volatile和synchronized的不同是最容易解释清楚的。volatile是变量修饰符,而synchronized则作用于一段代码或方法;看如下三句get代码:
- int i1; int geti1() {return i1;}
- volatile int i2; int geti2() {return i2;}
- int i3; synchronized int geti3() {return i3;}
geti1()得到存储在当前线程中i1的数值。多个线程有多个i1变量拷贝,而且这些i1之间可以互不相同。换句话说,另一个线程可能已经改 变了它线程内的i1值,而这个值可以和当前线程中的i1值不相同。事实上,Java有个思想叫“主”内存区域,这里存放了变量目前的“准确值”。每个线程 可以有它自己的变量拷贝,而这个变量拷贝值可以和“主”内存区域里存放的不同。因此实际上存在一种可能:“主”内存区域里的i1值是1,线程1里的i1值 是2,线程2里的i1值是3——这在线程1和线程2都改变了它们各自的i1值,而且这个改变还没来得及传递给“主”内存区域或其他线程时就会发生。
而geti2()得到的是“主”内存区域的i2数值。用volatile修饰后的变量不允许有不同于“主”内存区域的变量拷贝。换句话说,一个变量经 volatile修饰后在所有线程中必须是同步的;任何线程中改变了它的值,所有其他线程立即获取到了相同的值。理所当然的,volatile修饰的变量 存取时比一般变量消耗的资源要多一点,因为线程有它自己的变量拷贝更为高效。
既然volatile关键字已经实现了线程间数据同步,又要 synchronized干什么呢?呵呵,它们之间有两点不同。首先,synchronized获得并释放监视器——如果两个线程使用了同一个对象锁,监 视器能强制保证代码块同时只被一个线程所执行——这是众所周知的事实。但是,synchronized也同步内存:事实上,synchronized在“ 主”内存区域同步整个线程的内存。因此,执行geti3()方法做了如下几步:
1. 线程请求获得监视this对象的对象锁(假设未被锁,否则线程等待直到锁释放)
2. 线程内存的数据被消除,从“主”内存区域中读入(Java虚拟机能优化此步。。。[后面的不知道怎么表达,汗])
3. 代码块被执行
4. 对于变量的任何改变现在可以安全地写到“主”内存区域中(不过geti3()方法不会改变变量值)
5. 线程释放监视this对象的对象锁
因此volatile只是在线程内存和“主”内存间同步某个变量的值,而synchronized通过锁定和解锁某个监视器同步所有变量的值。显然synchronized要比volatile消耗更多资源。
更通俗的解释:
Volatile 字面的意思时易变的,不稳定的。在C#中也差不多可以这样理解。
编译器在优化代码时,可能会把经常用到的代码存在Cache里面,然后下一次调用就直接读取Cache而不是内存,这样就大大提高了效率。但是问题也随之而来了。
在多线程程序中,如果把一个变量放入Cache后,又有其他线程改变了变量的值,那么本线程是无法知道这个变化的。它可能会直接读Cache里的数据。但是很不幸,Cache里的数据已经过期了,读出来的是不合时宜的脏数据。这时就会出现bug。
用Volatile声明变量可以解决这个问题。用Volatile声明的变量就相当于告诉编译器,我不要把这个变量写Cache,因为这个变量是可能发生改变的。
[.net 多线程]volatile 摘录的更多相关文章
- C#多线程-volatile、lock关键字
volatile是C#中最简单的一种同步关键字,其意义是针对程序中一些敏感数据,不允许多线程同时访问,保证数据在任何访问时刻,最多有一个线程访问,以保证数据的完整性,虽与java中的synchroni ...
- Java多线程volatile和synchronized总结
volatile是轻量级的synchronized,在多处理器(多线程)开发中保证了共享变量的"可见性".可见性表示当一个线程修改了一个共享变量时,另外一个线程能读到这个修改的值. ...
- 多线程-volatile关键字和ThreadLocal
1.并发编程中的三个概念 原子性:一个或多个操作.要么全部执行完成并且执行过程不会被打断,要么不执行.最常见的例子:i++/i--操作.不是原子性操作,如果不做好同步性就容易造成线程安全问题. 可见性 ...
- java多线程-----volatile
谈谈Java中的volatile 内存可见性 留意复合类操作 解决num++操作的原子性问题 禁止指令重排序 总结 内存可见性 volatile是Java提供的一种轻量级的同步机制,在并发编程中, ...
- java多线程 -- volatile 关键字 内存 可见性
内存可见性(Memory Visibility) 1 内存可见性(Memory Visibility)是指当某个线程正在使用对象状态而另一个线程在同时修改该状态,需要确保当一个线程修改了对象状态后,其 ...
- 看一遍就懂,详解java多线程——volatile
多线程一直以来都是面试必考点,而volatile.synchronized也是必问点,这里我试图用容易理解的方式来解释一下volatile. 来看一下它的最大特点和作用: 一 使变量在多个线程间可见 ...
- [Java多线程] volatile 关键字正确使用方法
volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性,即多线程环境中,使用 volatile 关键字的变量仅可以保证不同线程读取变量时,可以读到最新修改的变量值,但是 ...
- C# volatile 摘录
C# 参考 volatile 关键字指示一个字段可以由多个同时执行的线程修改. 声明为 volatile 的字段不受编译器优化(假定由单个线程访问)的限制. 这样可以确保该字段在任何时间呈现的都是最新 ...
- 多线程--volatile
在解释volatile关键字之前,先说说java的指令重排以及代码的执行顺序. 指令重排: public void sum(){ int x = 1; int y = 2; int x = x + 1 ...
随机推荐
- 整数a整数b
namespace ConsoleApplication6{ class Program { static void Main(string[] args) { while (true) { Cons ...
- thinkphp中的_initialize方法
子类的_initialize方法自动调用父类的_initialize方法.而php的构造函数construct,如果要调用父类的方法,必须在子类构造函数显示调用parent::__construct( ...
- python开发面向对象基础:组合&继承
一,组合 组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合 人类装备了武器类就是组合 1.圆环,将圆类实例后传给圆环类 #!/usr/bin/env python #_*_ ...
- [新手教程]windows 2003 php环境搭建详细教程(转)
对于windows服务器的php环境配置一直是是新人朋友的难题,也难倒了很多高手.这里分享一个新手教程,给那些建站新人使用.本教程来自朋友吴文辉的博客,欢迎大家有时间可以访问他的博客:吴文辉博客htt ...
- Java之泛型
1. 概述 在引入泛型之前,Java类型分为原始类型.复杂类型,其中复杂类型分为数组和类.引入泛型后,一个复杂类型就可以在细分成更多的类型. 例如原先的类型List ...
- 使用ReentrantReadWriteLock类
读读共享 类ReentrantReadWriteLock的使用:写写互斥 读写互斥
- python学习——练习题(2)
""" 题目:企业发放的奖金根据利润提成.利润(I)低于或等于10万元时,奖金可提10%: 利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元 ...
- 「小程序JAVA实战」 小程序私有页面的生命周期以及导航(10)
转自:https://idig8.com/2018/08/09/xiaochengxu-chuji-10/ 之前讲了小程序全局的生命周期,今天咱们说说单个页面的生命周期!源码:https://gith ...
- 在linux中获取错误返回信息 &…
#include // void perror(const char *msg); #include // char *strerror(int errnum); #include //errno e ...
- Python基本数据类型之字符串、数字、布尔
一.数据类型种类 Python中基本数据类型主要有以下几类: Number(数字) String(字符串) Bool (布尔) List(列表) Tuple(元组) Sets(集合) Diction ...