技术开发 频道

.NET编程过程中的线程冲突

 那么这个函数也是线程安全的。

 这里有一个容易被忽略的问题,运算符。并不是所有的运算符(尤其是重载后的运算符)都是线程安全的。

 四、互斥锁

 有时候我们不得不面对线程不安全的问题,比如说在一开始提出来的那个例子,多线程完成100次任务,我们怎样才能解决这个问题,一个简单的办法就是给共享资源加上互斥锁。在C#中这很简单。比如一开始的那个例子:

 public static class Environment

 {public static int count = 0;//全局计数器

 }

 //…

 void ThreadMethod()//运行在每个线程的方法

 {

 while( true )

 {

 lock ( typeof( Environment ) )

 {

 if ( count >= 100 )//如果达到任务指标

 break;//中断线程执行

 DoSomething();//完成某个任务

 count++;}}}

 通过互斥锁,使得一个线程在使用count字段的时候,其他所有的线程都无法使用,而被阻塞等待。达到了避免线程冲突的效果。

 当然,这样的锁会使得这个多线程程序退化成同时只有一个线程在跑,所以我们可以把count++提前,使得lock的范围缩小,如这样:

 void ThreadMethod()//运行在每个线程的方法

 {

 while( true )

 {

 lock ( typeof( Environment ) )

 {

 if ( count++ >= 100 )//如果达到任务指标

 break;//中断线程执行

 }

 DoSomething();//完成某个任务

 }}

 最后来聊聊SyncRoot的问题。

 用.NET的一定会有很多朋友困惑,为什么对一个容器加锁,需要这样写:

 lock( Container.SyncRoot )

 而不是直接lock( Container )

 因为锁定一个容器并不能保证不会对这个容器进行修改,考虑这样一个容器:

 public class Collection

 {

 private ArrayList _list;

 public Add( object item )

 {

 _list.Add( item );

 }

 public object this[ int index ]

 {

 get { return _list[index]; }

 set { _list[index] = value;}

 }}

 看起来,将其lock起来后,就万事大吉了,没有人能修改这个容器,但实际上这个容器不过是用一个ArrayList实例来实现的,如果某段代码绕过这个容器而直接操作_list的话,则对这个容器对象lock也不可能保证容器不被修改了。

查看原文地址

0
相关文章