zoukankan      html  css  js  c++  java
  • 线程同步

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

  • 相关阅读:
    LENGTH()和CHAR_LENGTH()区别
    使用ibatis时 sql中 in 的参数赋值(转)
    数据库类型空间效率探索(五)- decimal/float/double/varchar
    MySQL用命令行复制表的方法
    升讯威微信营销系统开发实践:微信接口的 .NET 封装
    Github开源:Sheng.RabbitMQ.CommandExecuter (RabbitMQ 的命令模式实现)
    开源 & 免费使用 & 打包下载自行部署 :升讯威 周报系统
    开源 & 免费使用 & 打包下载自行部署 :升讯威 周报系统
    GitHub开源:升讯威ADO.NET增强组件 sheng.ADO.NET.Plus V1.3
    [源代码] SailingEase .NET Resources Tool (.NET 多语言资源编辑器)
  • 原文地址:https://www.cnblogs.com/czjone/p/1896495.html
Copyright © 2011-2022 走看看