• 线程同步


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

  • 相关阅读:
    Excel标题与索引的对应关系
    拼接LINQ动态表达式
    根据输入的模型属性表达式获取名称
    如何将页面的<br/>在Excel中正确换行
    针对VM从挂机-启动后,docker相关服务的无法使用问题!
    NIO(三):Selector选择器
    NIO(二):Channel通道
    Netty(一):netty的入门使用。
    设计模式(五):原型模式
    NIO(一):Buffer缓冲区
  • 原文地址:https://www.cnblogs.com/czjone/p/1896495.html
Copyright © 2020-2023  润新知