线程同步之原子操作

请看如下一个类

 

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
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它专门用于原子操作,请看如下改良代码:

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
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再执行赋值操作了,而是直接返回了,因此两个线程都得到了同一个等待句柄,也就解决了上面所说的线程同步问题,当然这段代码还存在一个小问题,您能看出来吗?

转载于:https://www.cnblogs.com/ren700622/archive/2010/08/06/1793700.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值