c#线程同步的几种方法

  

GPS平台,网站建设,软件开发,系统运维,找森大网络科技!
http://cnsendnet.taobao.com
来自森大科技官方博客http://www.cnsendblog.com/index.php/?p=405

  

我们在编程的时候,有时会使用多线程来解决问题,比如你的程序需要在后台处理一大堆数据,但还要使用户界面处于可操作状态,或者你的程序需要访问一些外部资源如数据库或网络文件等。这些情况你都可以创建一个子线程去处理,然而,多线程不可避免地会带来一个问题,就是线程同步的问题。如果这个问题处理不好,我们就会得到一些非预期的结果。
在网上也看过一些关于线程同步的文章,其实线程同步有好几种方法、下面我就简单的做一下归纳。
一、动荡的关键字
挥发性是最简单的一种同步方法,当然简单是要付出代价的。它只能在变量一级做同步,不稳定的含义就是告诉处理器,不要将我放入工作内存,请直接在主存操作我。(【转自www.bitsCN.com】)因此,当多线程同时访问该变量时,都将直接操作主存,从本质上做到了变量共享。
能够被标识为不稳定的必须是以下几种类型:(摘自MSDN)
?任何引用类型。
?任何指针类型(在一个不安全的环境)。
?sbyte类型、字节、短,ushort, int,使用uint, char、浮点数、布尔值。
?enum类型的enum基类型字节,sbyte,短,ushort, int或单位。


如:   
 <代码>公共类
  {
  私人int _i波动;
  公共int我
  {
  {回报_i;}
  集{_i=价值;}
  }
  }
   
  

但不稳定并不能实现真正的同步,因为它的操作级别只停留在变量级别,而不是原子级别。如果是在单处理器系统中,是没有任何问题的,变量在主存中没有机会被其他人修改,因为只有一个处理器,这就叫作处理器自洽性。但在多处理器系统中,可能就会有问题。每个处理器都有自己的数据cach,而且被更新的数据也不一定会立即写回到主存,所以可能会造成不同步,但这种情况很难发生,因为cach的读写速度相当快,冲的频率也相当高,只有在压力测试的时候才有可能发生,而且几率非常非常小。
二,锁关键字
锁是一种比较好用的简单的线程同步方式,它是通过为给定对象获取互斥锁来实现同步的。它可以保证当一个线程在关键代码段的时候,另一个线程不会进来,它只能等待,等到那个线程对象被释放,也就是说线程出了临界区。用法:

  
 <代码>公共void函数()
  {
  对象lockThis=新对象();
  锁(lockThis)
  {//thread-sensitive资源的访问。
  }
  }
   
  

锁的参数必须是基于引用类型的对象,不要是基本类型像bool, int什么的,这样根本不能同步,原因是锁的参数要求是对象,如果传入int,势必要发生装箱操作,这样每次锁的都将是一个新的不同的对象。最好避免使用公共类型或不受程序控制的对象实例,因为这样很可能导致死锁。特别是不要使用字符串作为锁的参数,因为字符串被CLR“暂留”,就是说整个应用程序中给定的字符串都只有一个实例,因此更容易造成死锁现象。建议使用不被“暂留”的私有或受保护成员作为参数。其实某些类已经提供了专门用于被锁的成员,比如数组类型提供SyncRoot,许多其它集合类型也都提供了SyncRoot。
所以,使用锁应该注意以下几点:
1,如果一个类的实例是公共的,最好不要锁(这)。因为使用你的类的人也许不知道你用了锁,如果他新了一个实例,并且对这个实例上的锁,就很容易造成死锁。
2,如果MyType是公共的,不要锁(typeof (MyType))
3,永远也不要锁定一个字符串
三,System.Threading。联锁
对于整数数据类型的简单操作,可以用联锁类的成员来实现线程同步,存在于系统。线程命名空间.Interlocked类有以下方法:增量、减量、交换和CompareExchange。使用增量和减量可以保证对一个整数的加减为一个原子操作.Exchange方法自动交换指定变量的值.CompareExchange方法组合了两个操作:比较两个值以及根据比较的结果将第三个值存储在其中一个变量中。比较和交换操作也是按原子操作执行的。如:

  
 <代码> int i=0;
  System.Threading.Interlocked。增量(ref);
  Console.WriteLine(我);
  System.Threading.Interlocked。减量(ref);
  Console.WriteLine(我);
  System.Threading.Interlocked。交易所(ref我,100);
  Console.WriteLine(我);
  System.Threading.Interlocked。CompareExchange (ref我,100);
   
  

输出:
 C #线程同步的几种方法”> <h2 class=c#线程同步的几种方法