但她们所访问的数额或艺术并差别(不交叉),使其近来无法被别的线程访问

  考虑一种我们平常遇上的情事:有一对全局变量和共享的类变量,大家要求从差别的线程来更新它们,能够由此选择System.Threading.Interlocked类完结如此的任务,它提供了原子的,非模块化的整数更新操作。

在.Net的少数对象里面,在读取里面的多少的还要还是能修改数据,那类的对象就是“线程安全”。
但对此团结编写的代码段而言,就不需选择线程同步技术来保险数据的完整性和科学了。

  还有你可以选用System.Threading.Monitor类锁定目的的章程的一段代码,使其近年来无法被其余线程访问。

记住那一点:
① 、若是一个目的(或变量)不会同时被多个别的线程访问,那么那么些目的是不需采用线程同步的。
二 、假诺即便有五个线程同时做客三个对象,但他们所访问的数量或措施并差异(不交叉),那那种意况也不需采纳线程同步。
比如说上例中的那些企行业内部部要是有 T 和 Q 四个人,但他们的报酬分别是由 A 和
B CEO的,那么那几个薪水的拍卖就不要求线程同步了。
三 、即使八个指标会同时被四个别的线程访问,一般只需为这些指标添加线程同步的代码,而其他线程是不需添加额外轮代理公司码的。

  System.Threading.WaitHandle类的实例能够用来封装等待对共享财富的独占访问权的操作系统特定的靶子。特别对于非受管代码的互操作难点。

Monitor的常用方法:Enter和Exit都以静态方法,功用跟lock语句的八个花括号一致。

  System.Threading.Mutex用于对七个复杂的线程同步的题目,它也同意单线程的访问。

而采取 Mutex 就不需声喜宝(Nutrilon)个“令牌”对象了,但要实例化之后才方可选用:

  像马努alReset伊芙nt和AutoReset伊夫nt那样的一块儿事件类扶助二个类布告任何事件的线程。

个中的WaitOne为等待方法,一向等到Mutex 被释放结束。初叶的情景下,Mutex
对象是高居自由状态的,而一旦实施了WaitOne方法之后,它

  不商讨线程的一块难题,等于对八线程编制程序知之甚少,但是我们要尤其小心的利用二十四线程的联合署名。在利用线程同步时,我们事先就要要力所能及科学的规定是十一分指标和艺术有恐怕引致死锁(死锁正是装有的线程都停下了对应,都在等者对方释放财富)。还有赃数据的标题(指的是同一时半刻间八个线程对数据作了操作而导致的分裂),那一个不易于通晓,这么说呢,有X和Y四个线程,线程X从文件读取数据并且写多少到数据结构,线程Y从这些数据结构读数据并将数据送到任何的微机。借使在Y读数据的同时,X写入数据,那么肯定Y读取的多寡与事实上存款和储蓄的数据是不平等的。那种气象显然是咱们应该防止生出的。少量的线程将使得刚刚的标题发生的可能率要少的多,对共享财富的拜会也更好的协同。

就被抓走了,平昔到被调用了ReleaseMutex方法之后才被假释。

  .NET Framework的CLR提供了三种办法来形成对共享资源,诸如全局变量域,特定的代码段,静态的和实例化的章程和域。

利用这两种格局都有三个要注意的难题,正是在独占代码段里面要是引起了丰富,恐怕会使“令牌”对象不被假释,那样程序就会直接地死等

  (1)
代码域同步:使用Monitor类能够协同静态/实例化的不二法门的整个代码或然局部代码段。不协理静态域的一道。在实例化的形式中,this指针用于共同;而在静态的方法中,类用于共同,那在后头会讲到。

下去了。

  (2) 手工同步:使用不一样的同步类(诸如WaitHandle, Mutex,
ReaderWriterLock, 马努alReset伊芙nt, AutoReset伊芙nt
和Interlocked等)创造本身的同台机制。这种同步格局要求你协调手动的为差异的域和措施同步,那种共同格局也得以用于进度间的一道和对共享能源的等待而造成的死锁解除。

 

  (3)
上下文同步:使用SynchronizationAttribute为ContextBoundObject对象创设不难的,自动的一块。那种共同格局仅用于实例化的不二法门和域的联合署名。全部在同一个左右文域的目的共享同二个锁。
Monitor Class

 

  在加以的年华和点名的代码段只可以被三个线程访问,Monitor
类格外适合于那种状态的线程同步。这些类中的方法都是静态的,所以不供给实例化这么些类。上面一些静态的不二法门提供了一种体制用来2只对象的造访从而幸免死锁和掩护数据的一致性。

  Monitor.Enter 方法:在钦定对象上收获排他锁。

  Monitor.TryEnter 方法:试图拿走钦点对象的排他锁。

  Monitor.Exit 方法:释放钦赐对象上的排他锁。

  Monitor.Wait
方法:释放对象上的锁并阻塞当前线程,直到它再也得到该锁。

  Monitor.Pulse 方法:布告等待队列中的线程锁定目的境况的改变。

  Monitor.PulseAll 方法:布告全体的等待线程对象情形的改动。

  通过对点名对象的加锁和解锁能够同步代码段的拜会。Monitor.Enter,
Monitor.TryEnter 和
Monitor.Exit用来对点名对象的加锁和平化解锁。一旦获得(调用了Monitor.Enter)钦定对象(代码段)的锁,别的的线程都不可能博得该锁。举个例子来说呢,线程X得到了贰个对象锁,这一个目标锁能够自由的(调用Monitor.Exit(object)
or Monitor.Wait)。当这些指标锁被放走后,Monitor.Pulse方法和
Monitor.PulseAll方法公告就绪队列的下一个线程举行和别的全体就绪队列的线程将有时机获得排他锁。线程X释放了锁而线程Y获得了锁,同时调用Monitor.Wait的线程X进入等待队列。当从当下锁定目的的线程(线程Y)受到了Pulse或PulseAll,等待队列的线程就进来就绪队列。线程X重新获得对象锁时,Monitor.Wait才回来。即使全部锁的线程(线程Y)不调用Pulse或PulseAll,方法或者被不鲜明的锁定。Pulse,
PulseAll and
Wait必须是被一起的代码段鄂被调用。对每1个手拉手的对象,你须要有日前有所锁的线程的指针,就绪队列和等待队列(包括须求被打招呼锁定指标的气象变化的线程)的指针。

  你恐怕会问,当多个线程同时调用Monitor.Enter会发生如何业务?无论那七个线程地调用Monitor.Enter是何等地接近,实际上肯定有3个在前,二个在后,因而永远只会有2个赢得对象锁。既然Monitor.Enter是原子操作,那么CPU是不容许偏好贰个线程而不爱好别的3个线程的。为了获得更好的性质,你应该延迟后1个线程的获得锁调用和当下释放前三个线程的靶子锁。对于private和internal的靶子,加锁是实惠的,可是对于external对象有或者导致死锁,因为不相干的代码可能因为分化的目标而对同一个对象加锁。

  假使您要对一段代码加锁,最好的是在try语句里面参预设置锁的讲话,而将Monitor.Exit放在finally语句里面。对于全体代码段的加锁,你能够动用MethodImplAttribute(在System.Runtime.Compiler瑟维斯s命名空间)类在其构造器中设置同步值。那是一种可以代替的法子,当加锁的法子再次来到时,锁也就被假释了。假如急必要火速释放锁,你能够利用Monitor类和C#
lock的宣示代替上述的艺术。

  让大家来看一段使用Monitor类的代码:

public void some_method()
{

int a=100;

int b=0;

Monitor.Enter(this);

//say we do something here.

int c=a/b;

Monitor.Exit(this);

}

  下边包车型大巴代码运维会生出难题。当代码运转到int c=a/b;
的时候,会抛出一个12分,Monitor.Exit将不会回来。因而那段程序将挂起,其余的线程也将得不到锁。有两种格局能够消除地点的标题。第五个章程是:将代码放入try…finally内,在finally调用Monitor.Exit,那样的话最后一定会释放锁。第二种艺术是:利用C#的lock()方法。调用这么些点子和调用Monitoy.Enter的效益功能是一律的。可是那种措施一旦代码执行超出范围,释放锁将不会自动的发生。见下边包车型地铁代码:

public void some_method()
{

int a=100;

int b=0;

lock(this);

//say we do something here.

int c=a/b;

}

  C#
lock申明提供了与Monitoy.Enter和Monitoy.Exit同样的功效,那种艺术用在您的代码段不可能被别的独立的线程中断的情状。

WaitHandle Class

  WaitHandle类作为基类来行使的,它同意多少个等待操作。那个类包装了win32的同台处理方法。WaitHandle对象公告别的的线程它要求对能源排他性的造访,其余的线程必须等待,直到WaitHandle不再动用能源和等候句柄没有被选取。上面是从它一连来的多少个类:

  Mutex 类:同步基元也可用于进度间协同。

  AutoReset伊芙nt:通知3个或多少个正在等待的线程已产滋事变。无法继续此类。

  马努alReset伊芙nt:当通知三个或多少个正在等待的线程事件已产生时出现。不恐怕继续此类。

  这么些类定义了部分信号机制使得对财富排他性访问的占有和假释。他们有二种境况:signaled

nonsignaled。Signaled状态的守候句柄不属于别的线程,除非是nonsignaled状态。拥有等待句柄的线程不再接纳等待句柄时用set方法,别的的线程可以调用Reset方法来改变状态或然私下1个WaitHandle方法要求全数等待句柄,那一个主意见上面:

  WaitAll:等待钦命数组中的全体因素收到信号。

  WaitAny:等待钦命数组中的任一元素收到信号。

  WaitOne:当在派生类中重写时,阻塞当前线程,直到当前的 WaitHandle
收到信号。

  这一个wait方法阻塞线程直到二个还是愈多的2只对象吸收信号。

  WaitHandle对象封装等待对共享财富的独占访问权的操作系统特定的指标无论是收管代码依然非受管代码都得以选择。可是它并未Monitor使用便捷,Monitor是一心的受管代码而且对操作系统财富的使用越发有功效。

Mutex Class

  Mutex是其余一种实现线程间和跨进程同步的不二法门,它同时也提供经过间的同台。它同意2个线程独占共享能源的还要阻止别的线程和进度的造访。Mutex的名字就很好的认证了它的主人对财富的排他性的占有。一旦3个线程拥有了Mutex,想得到Mutex的任何线程都将挂起直至占有线程释放它。Mutex.ReleaseMutex方法用于释放Mutex,多少个线程能够屡屡调用wait方法来呼吁同叁个Mutex,可是在出狱Mutex的时候必须调用同样次数的Mutex.ReleaseMutex。若是没有线程占有Mutex,那么Mutex的景色就改为signaled,不然为nosignaled。一旦Mutex的图景成为signaled,等待队列的下3个线程将会取得Mutex。Mutex类对应与win32的CreateMutex,创立Mutex对象的办法万分简单,常用的有上边三种艺术:

  二个线程能够通过调用WaitHandle.WaitOne 或 WaitHandle.WaitAny 或
WaitHandle.WaitAll获得Mutex的拥有权。如若Mutex不属于别的线程,上述调用将使得线程拥有Mutex,而且WaitOne会立时回到。不过一旦有任何的线程拥有Mutex,WaitOne将沦为无限期的等候直到获取Mutex。你能够在WaitOne方法中内定参数即等待的大运而防止无限期的等候Mutex。调用Close作用于Mutex将释放具有。一旦Mutex被创建,你能够通过GetHandle方法取得Mutex的句柄而给WaitHandle.WaitAny
或 WaitHandle.WaitAll 方法运用。

  下边是三个示范:

public void some_method()
{

int a=100;

int b=20;

Mutex firstMutex = new Mutex(false);

FirstMutex.WaitOne();

//some kind of processing can be done here.

Int x=a/b;

FirstMutex.Close();

}

  在地方的例证中,线程创造了Mutex,不过开头并没有表达拥有它,通过调用WaitOne方法拥有Mutex。

Synchronization Events

  同步时间是部分等候句柄用来文告别的的线程产生了何等业务和能源是可用的。他们有七个情景:signaled
and nonsignaled。AutoReset伊夫nt 和 马努alReset伊芙nt就是那种共同事件。

AutoResetEvent Class

  这一个类能够通报多个或三个线程发惹祸变。当多个等候线程获得释放时,它将状态转换为signaled。用set方法使它的实例状态成为signaled。然则如若等待的线程被文告时间变成signaled,它的转台将机关的变成nonsignaled。如若没有线程侦听事件,转台将有限支撑为signaled。此类不能被持续。

ManualResetEvent Class

  这一个类也用来打招呼3个或多少个线程事件产生了。它的处境能够手动的被设置和重置。手动重置时间将保证signaled状态直到马努alReset伊夫nt.Reset设置其情状为nonsignaled,或保持状态为nonsignaled直到马努alReset伊芙nt.Set设置其状态为signaled。那么些类不能够被接续。

Interlocked Class

  它提供了在线程之间共享的变量访问的一起,它的操作时原子操作,且被线程共享.你能够由此Interlocked.Increment

Interlocked.Decrement来扩大或减中国少年共产党享变量.它的有点在于是原子操作,也正是说那么些主意可以代贰个整型的参数增量并且重返新的值,全数的操作就是一步.你也得以运用它来内定变量的值只怕检查多个变量是或不是等于,假若相等,将用内定的值代替当中贰个变量的值.

ReaderWriterLock class

  它定义了一种锁,提供唯一写/多读的体制,使得读写的同步.任意数指标线程都足以读数据,数据锁在有线程更新数据时将是急需的.读的线程能够获得锁,当且仅当那里没有写的线程.当没有读线程和任何的写线程时,写线程能够赢得锁.因而,一旦writer-lock被呼吁,全体的读线程将不可能读取数据直到写线程访问完成.它扶助暂停而防止死锁.它也支撑嵌套的读/写锁.协助嵌套的读锁的艺术是ReaderWriterLock.AcquireReaderLock,假如叁个线程有写锁则该线程将中止;

  协助嵌套的写锁的法门是ReaderWriterLock.AcquireWriterLock,倘使一个线程有读锁则该线程暂停.假若有读锁将便于倒是死锁.安全的措施是应用ReaderWriterLock.UpgradeToWriterLock方法,那将使读者升级到写者.你能够用ReaderWriterLock.DowngradeFromWriterLock方法使写者降级为读者.调用里德rWriterLock.ReleaseLock将释放锁,
ReaderWriterLock.RestoreLock将重新装载锁的气象到调用ReaderWriterLock.ReleaseLock往日.

来源:http://hi.baidu.com/jia818915/blog/item/d4e0374f4263e433aec3ab79.html
 

 

相关文章