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

  • 相关阅读:
    【LeetCode】17. Letter Combinations of a Phone Number
    【LeetCode】16. 3Sum Closest
    【LeetCode】15. 3Sum 三个数和为0
    【LeetCode】14. Longest Common Prefix 最长前缀子串
    【LeetCode】13. Roman to Integer 罗马数字转整数
    【LeetCode】12. Integer to Roman 整型数转罗马数
    【LeetCode】11. Container With Most Water
    【LeetCode】10. Regular Expression Matching
    Models of good programmer
    RSA Algorithm
  • 原文地址:https://www.cnblogs.com/czjone/p/1896495.html
Copyright © 2011-2022 走看看