线程同步

只愿长相守 提交于 2020-04-04 06:26:56

C#用于线程同步的方法有lock statement,Interlocked class,Monitor class,wait handles(抽象基类,后续的Mutex,Semaphore,Event均为WaitHandle的实现子类),Mutex,Semaphore,Events,ReaderWriterLockSlim,其中lock statement, Interlocked class以及Monitor class可以用于同一进程的线程间同步,而Mutex,Semaphore,Events以及ReaderWriterLockSlim可以用于不同进程的线程间同步。

lock statement:

使用C#的关键字lock进行代码区域加锁:

lock (obj)  //锁定引用对象实例,不能是值对象,用于对象实例级别的代码同步

{
//同步代码区域

或者

lock (typeof(class))  //锁定类对象,用于类级别的静态代码同步

//同步代码区域

Interlocked class:

Interlocked class是一种相对于其他同步方法更快的但只能用于变量修改同步的方法。

Interlocked class提供了以下静态方法用于同步变量的修改操作:

Increment,Decrement,Exchange,CompareExchange,Add,Read(用于在32系统从内存中原子的读取64比特值)

Monitor class:

Monitor class提供了一些静态方法用于实现线程同步,与lock statement相比可以指定加锁的超时时间。

//无超时

Monitor.Enter(obj);

//同步代码区域

finally

Monitor.Exit(obj);

//超时

if (Monitor.TryEnter(obj, 500))

  try

  {

  //同步代码区域

  }

  finally

  {

    Monitor.Exit(obj);

  }

else

//加锁超时

Wait handle:

WaitHandle是一个抽象基类,表示一个可以被signal的资源对象,定义了如下方法:

WaitOne  实例方法,用于等待资源对象被signal,可以指定超时时间

WaitAll     静态方法,等待waithandle数组中的所有资源对象被signal

WaitAny   静态方法,等待waithandle数组中的任一资源对象被signal,返回被signal的资源对象在数组中的索引,可以指定超时时间,如果超时则返回WaitTimeOut

Mutex:

Mutex每次只能有一个线程加锁成功,Mutex可以指定创建的时候是否加锁以及可以为Mutex指定一个名字,有名的Mutex可以用于不同进程间的线程互斥,而无名Mutex只能用于同一进程中的线程互斥,另外Mutex的构造函数还可以指定一个out参数用于接收构造的Mutex对象是创建了一个新的Mutex互斥体还是打开了一个已经存在的Mutex互斥体操作,除了使用new创建Mutex对象以外还可以调用Mutex.OpenExisting方法打开一个已经存在的互斥体。

Mutex继承自WaitHandle,因此可以调用WaitHandle定义的wait系列方法加锁,释放锁则调用Mutex.ReleaseMutex方法。

if (mutex.WaitOne())
{
  try
  {
    // synchronized region
  }
  finally
  {
    mutex.ReleaseMutex();
  }
}
else
{
  // some problem happened while waiting
}

Semaphore:

跟Mutex的区别是semaphore是一个计数型Mutex,也就是一次可以有多个线程同时锁定Semaphore,Semaphore的计数代表有多个可供访问的资源,因此也就允许同时计数个线程加锁访问。

Event:

Event分为ManualResetEvent以及AutoResetEvent,ManualResetEvent当调用Set对Event进行Singal之后所有等待此Event被Singal的线程均从睡眠等待中返回,调用Reset将Event重置为未singal状态。而AutoResetEvent与ManualResetEvent不同的是当调用Set对Event进行Singal之后只有一个线程(优先级别最高的线程)能够从等待中返回并且返回之前将Event重置为未singal状态。

ReaderWriterLockSlim:

读写锁,多个读线程可以同时读锁定,读锁与写锁互斥,写锁之间也互斥,提供方法如下:

TryEnterReadLock, EnterReadLock, ExitReadLock 操作读锁

TryEnterUpgradableReadLock, EnterUpgradableReadLock, ExitUpgradableReadLock 操作可更新读锁(也就是在拥有读锁的时候可以不释放读锁升级为写锁)

TryEnterWriteLock, EnterWriteLock, ExitWriteLock 操作写锁

ReaderWriterLockSlim的构造函数能够指定读写锁是否为可递归锁,也就是同一线程能对同一读写锁进行多次加锁操作而不会死锁。 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!