爱学习的站长www.mmic.net.cn

www.mmic.net.cn 欢迎学习共同成长
公告信息
www.mmic.net.cn 欢迎学习共同成长
文章分类
文章档案
文章
怎样编写安全的多线程C#程序
2011/7/26 13:23:39
与多线程相关的两个常见的需要解决的问题是:临界资源保护和线程间的同步依赖,每一种语言都提供了自己的一套设施(有的语言可能需要借助OS的API)来解决这两个问题,C#提供了更方便灵活的解决方案,首先C#可以允许我们在不同的级别上加锁,也就是说我们可以控制加锁的粒度。其次,C#提供了一套内置的线程安全的容器,方便我们的使用。

    一.不同级别(Level)上的同步:
    1.object level 同步
    对应的class必须从ContextBoundObjectpdf继承(同步上下文context,使所有的方法调用能被截获),并且在class上运用SynchronizationAttribute 。

    2.Method level 同步
    System.Runtime.CompilerServicepdf空间包含的一些属性将影响CLR在运行期间的行为。特性MethodImplAttribute可以用于需要进行同步控制的方法上。

    3.code segment level 同步
    (1)Monitor类(主要是静态方法) 
Monitor.Enter(obj)//获得加在对象obj上的锁 ... Monitor.Exit(obj)//释放锁 //上面两句之间的代码相当于lock(obj){...} Monitor.TryEnter(obj)//该方法立即返回,如果返回值为false,则接下来不需要Monitor.Exit(obj)。 //以下几个方法用于线程间的交互 ==》 解决同步依赖 Monitor.Wait(obj)//等待脉冲消息。释放对象上的锁并阻塞当前线程,以后只有其它线程调用Pulse或PulseAll时才会给它再次获得锁的机会 Monitor.Pulse(obj)//发射脉冲消息( 只有得到锁后才能发射,而且发射不会自动释放锁) Monitor.PulseAll(obj)

    注意:
    (1)Monitor 锁定对象,只能在Enter()和Exit()之间的代码块中调用Wait和Pulse
    (2)不能在一个线程中获得锁,而在另一个线程中释放锁。这样会产生锁丢失。 获得锁和释放锁应该在同一个线程中完成。
    (3)lock语句

lock(obj) { 需要进行同步的代码 }

    (4)ReaderWriterLock类
    实现单写多读程序的锁。

AcquireReaderLock()//当没有写程序线程占用锁时,就可获得锁 AcquireWriterLock()//当没有任何读写程序线程占用锁时,才可获得锁 ReleaseReaderLock() ReleaseWriterLock()

     (5)ManualResetEvent

Set()方法将状态设置为有信号 Reset()将其设置为无信号 WaitOne()将阻塞到其有信号为止,若调用WaitOne的时刻就是有信号的,将不会阻塞

    (6)AutoResetEvent
    与ManualResetEvent的区别是pdf,AutoResetEvent.WaitOne()会自动改变事件对象的状态,即AutoResetEvent.WaitOne()每执行一次,事件的状态就改变一次。有信号-->无信号;无信号-->有信号

    说明:
    (1)无论是Monitor还是lock、ReaderWriterLock都只对引用类型的对象有效,因为引用类型的对象有一个隐藏的sync#字段,该字段的作用就是作为加锁的标记。
    (2)上述的各种设施中,只有Monitor 和ManualResetEvent/AutoResetEvent 能解决线程间的同步依赖问题,而其它的设施主要用于解决临界资源共享。

    4.member level同步
    (1)Interlocked类(主要是静态方法)
    同步一个由许多线程共享的变量。

Decrement(ref int);//使变量减1 Increment(ref int);//使变量加1 //以上两个方法仅针对类int变量 Exchange(ref object, object);

    (2)ThreadStaticAttribute pdf
    该特性用于修饰静态变量,被该特性修饰的静态变量在每个线程中都有自己的副本。

    二.创建线程安全的对象

Hashtable h = Hashtable.Synchronized(new Hashtable()) ;

    ArrayList等容器也提供类似操作。

新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"
 技术   浏览(2306)   评论(0)   关键字
  
Copyright © 2010-2020 power by CYQ.Blog - 秋色园 v2.0 All Rights Reserved