每天进步一点点
首先咱们可以看一下MSDN对volatile的定义: The volatile keyword indicates that a field can be modified in the program by something such as the operating system, the hardware, or a concurrently executing thread.
The system always reads the current value of a volatile object at the point it is requested, even if the previous instruction asked for a value from the same object. Also, the value of the object is written immediately on assignment.
The volatile modifier is usually used for a field that is accessed by multiple threads without using the lock statement to serialize access. Using the volatile modifier ensures that one thread retrieves the most up-to-date value written by another thread. 然后呢,咱们可以看到在Singleton模式中对多线程的优化
posted on 2007-11-12 12:36 逖靖寒 阅读(4486) 评论(7) 编辑 收藏
其实Volatile是由于编译器优化所造成的一个Bug而引入的关键字。 int a = 10; int b = a; int c = a; 理论上来讲每次使用a的时候都应该从a的地址来读取变量值,但是这存在一个效率问题,就是每次使用a都要去内存中取变量值,然后再通过系统总线传到CPU处理,这样开销会很大。所以那些编译器优化者故作聪明,把a读进CPU的cache里,像上面的代码,假如a在赋值期间没有被改变,就直接从CPU的cache里取a的副本来进行赋值。但是bug也显而易见,当a在赋给b之后,可能a已经被另一个线程改变而重新写回了内存,但这个线程并不知道,依旧按照原来的计划从CPU的cache里读a的副本进来赋值给c,结果不幸发生了。 于是编译器的开发者为了补救这一bug,提供了一个Volatile让开发人员为他们的过失埋单,或者说提供给开发人员了一个选择效率的权利。当变量加上了Volatile时,编译器就老老实实的每次都从内存中读取这个变量值,否则就还按照优化的方案从cache里读。 回复 引用
@dlwxq呵呵 王老师说得对 回复 引用
1楼的说法是错误的,既然volatile是编译阶段的控制,那如何能够控制CPU是从内存还是cache中取数据。 volatile是告诉编译器不能从寄存器中取数据,而是从内存中取,至于CPU到底是从内存中取还是在data cache/l2 cache中取,取决于volatile指的数据对应的memory对于CPU是否可cache的,只要是可cache的并且能够cache命中,CPU还是直接从cache中取。 回复 引用
MSDN Library中写到: volatile 关键字表示字段可能被多个并发执行线程修改。声明为 volatile 的字段不受编译器优化(假定由单个线程访问)的限制。这样可以确保该字段在任何时间呈现的都是最新的值。[从这里可以看出,如果使用了该修饰符,则应该是每次都从内存中读取的,对吧!] volatile 修饰符通常用于由多个线程访问而不使用 lock 语句(C# 参考)语句对访问进行序列化的字段。有关在多线程方案中使用 volatile 的示例,请参见如何:创建和终止线程(C# 编程指南)。 volatile 关键字可应用于以下类型: 引用类型。 指针类型(在不安全的上下文中)。 整型,如 sbyte、byte、short、ushort、int、uint、char、float 和 bool。 具有整数基类型的枚举类型。 已知为引用类型的泛型类型参数。 IntPtr 和 UIntPtr。 所涉及的类型必须是类或结构的字段。不能将局部变量声明为 volatile。 回复 引用
3楼说的非常准确, 大家不要拿什么 msdn引用的一堆废话来忽悠, 理解了就没啥了。volatile 对于cache过的memory而又有多master的,这个关键字的作用难说了 回复 引用
事实上,3楼说的并不精确,自然CPU可能是从cache1/2中取数据,这一点都不假,可是如果其他线程修改了内存的数据后,相应的cache中的页会被置为无效,那么下次再来读取肯定不会cache命中,这样被volatile修饰的值始终还是真正被修改过的值,这些在操作系统的分页机制中有详细的描述。所以我认为5楼的理解还是有偏差的。不知道我说的对否,欢迎讨论! 回复 引用
有时虽然cache中的页被置为无效,但有时可能会出现Memery的值在CPU的寄存中, 回复 引用
Powered by: 博客园 Copyright © 逖靖寒