线程同步之原子操作

请看如下一个类

 

代码
1 public class A
2 {
3 private ManualResetEvent p_mEvt;
4
5 public WaitHandle Evt
6 {
7 get
8 {
9 if(p_mEvt==null)
10 p_mEvt=new ManualResetEvent(false);
11 return p_mEvt;
12 }
13 }
14 }

A类中申明了一个只读属性的等待句柄,而我们没有在构造函数里初始化它,这是有足够理由的,那就是节约资源,直到有使用到它才创建它,否则就根本不创建它,这在ms的Control里经常可以看到,这是因为Control里的对象属性太多了,如果在Control的构造函数中都对它们进行初始化操作的话,那占用的资源是可想而知的.正因为如此,这段代码在多线程运行中就会出现问题了,比如有两个线程都取该属性,线程1在运行完语句9时发现满足条件即将运行语句10,这时线程1的时间片用完了,被系统挂起,而线程2开始运行了,它运行到9时也发现满足条件(因为线程1在10挂起,它还没有new操作)于是运行了10完成一个new操作后获得了一个句柄返回了,这时线程1又运行了,而它是直接运行new操作然后返回的,这样一来两个线程获得了两个不同的等待句柄,那这两个线程中依赖于等待句柄操作的代码运行结果肯定是不正确的了.

解决办法呢?有的,ms提供类一个类Interlocked它专门用于原子操作,请看如下改良代码:

代码
1 public class A
2 {
3 private ManualResetEvent p_mEvt;
4
5 public WaitHandle Evt
6 {
7 get
8 {
9 if(p_mEvt==null)
10 Interlocked.CompareExchange(ref p_mEvt,new ManualResetEvent(false),null);
11 return p_mEvt;
12 }
13 }
14 }

是的,就是对new方法改成Interlocked.CompareExchange方法,因为该方法确保原子操作,也就是说上面的线程1再运行时它会发现p_mEvt已经不是null了,它就不会对p_mEvt再执行赋值操作了,而是直接返回了,因此两个线程都得到了同一个等待句柄,也就解决了上面所说的线程同步问题,当然这段代码还存在一个小问题,您能看出来吗?

posted on 2010-08-06 09:40  悠竹客  阅读(696)  评论(0编辑  收藏  举报

导航