今天突然理解了“volatile”

首先咱们可以看一下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模式中对多线程的优化

 1using System;
 2using System.Configuration;
 3
 4namespace HeadFirstDesignPatterns.Singleton.InterestRate
 5{
 6    /// <summary>
 7    /// Summary description for RateSingleton.
 8    /// </summary>

 9    public class RateSingleton
10    {
11        private volatile static RateSingleton uniqueInstance;
12        private static object syncRoot = new Object();
13
14        private double currentRate = 
15            Convert.ToDouble(ConfigurationSettings.AppSettings["CurrentInterestRate"]);
16
17        public double CurrentRate
18        {
19            get
20            {
21                return currentRate;
22            }

23            set
24            {
25                currentRate = value;
26            }

27        }

28
29        private RateSingleton()
30        {}
31
32        public static RateSingleton GetInstance()
33        {
34            //The approach below ensures that only one instance is created and only 
35            //when the instance is needed. Also, the uniqueInstance variable is 
36            //declared to be volatile to ensure that assignment to the instance variable 
37            //completes before the instance variable can be accessed. Lastly, 
38            //this approach uses a syncRoot instance to lock on, rather than 
39            //locking on the type itself, to avoid deadlocks.
40
41            if(uniqueInstance == null)
42            {
43                lock (syncRoot)
44                {
45                    if(uniqueInstance == null)
46                    {
47                        uniqueInstance = new RateSingleton();
48                    }

49                }

50            }

51            return uniqueInstance;
52        }

53    }

54}

55
posted @ 2007-11-12 12:36 逖靖寒 阅读(1773) 评论(4)  编辑 收藏 所属分类: 读书.NET 编程

  回复  引用    
#1楼 2007-12-05 19:21 | dlwxq [未注册用户]
其实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里读。

  回复  引用    
#2楼 2007-12-05 20:33 | 郭鹏 [未注册用户]
@dlwxq
呵呵 王老师说得对
  回复  引用    
#3楼 2008-04-17 23:20 | AlickG [未注册用户]
1楼的说法是错误的,既然volatile是编译阶段的控制,那如何能够控制CPU是从内存还是cache中取数据。

volatile是告诉编译器不能从寄存器中取数据,而是从内存中取,至于CPU到底是从内存中取还是在data cache/l2 cache中取,取决于volatile指的数据对应的memory对于CPU是否可cache的,只要是可cache的并且能够cache命中,CPU还是直接从cache中取。

  回复  引用    
#4楼 2008-05-12 16:34 | Bob.Liu [未注册用户]
MSDN Library中写到:

volatile 关键字表示字段可能被多个并发执行线程修改。声明为 volatile 的字段不受编译器优化(假定由单个线程访问)的限制。这样可以确保该字段在任何时间呈现的都是最新的值。[从这里可以看出,如果使用了该修饰符,则应该是每次都从内存中读取的,对吧!]

volatile 修饰符通常用于由多个线程访问而不使用 lock 语句(C# 参考)语句对访问进行序列化的字段。有关在多线程方案中使用 volatile 的示例,请参见如何:创建和终止线程(C# 编程指南)。

volatile 关键字可应用于以下类型:

引用类型。

指针类型(在不安全的上下文中)。

整型,如 sbyte、byte、short、ushort、int、uint、char、float 和 bool。

具有整数基类型的枚举类型。

已知为引用类型的泛型类型参数。

IntPtr 和 UIntPtr。

所涉及的类型必须是类或结构的字段。不能将局部变量声明为 volatile。


标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      


相关链接: