c#多线程学习笔记二

1:Mutex类可以同步两个单独的程序,只对一个线程授予对共享资源的独占访问。具名的互斥量是全局的操作系统对象,请务必正确关闭互斥量,最好使用using代码块来包裹互斥量对象。

示例代码:

static void Main(string[] args)
  {
   const string MutexName = "CSharpThreadingCookbook";
   using (var m = new Mutex(false, MutexName))
   {
  //设置5秒钟内获取该互斥量
    if (!m.WaitOne(TimeSpan.FromSeconds(5), false))
    {
     WriteLine("Second instance is running!");
    }
    else
    {
     WriteLine("Running!");
     ReadLine();
     m.ReleaseMutex();//释放互斥量
    }
   }
  }
2:SemaphoreSlim类限制了访问同一资源的线程数量。Semaphore类是SemaphoreSlim类的一个老版本,Semaphore类可以像Mutex一样具名,并且可以在不同的程序中同步线程,但是SemaphoreSlim并不使用Windows内核信号量,而且也不支持进程间同步,所以在跨程序同步的场景下可以使用Semaphore。
3:CountDownEvent类可以等待一定数量的线程完成操作。
示例代码:
static void Main(string[] args)
  {
   WriteLine("Starting two operations");
   var t1 = new Thread(() => PerformOperation("Operation 1 is completed", 4));
   var t2 = new Thread(() => PerformOperation("Operation 2 is completed", 8));
   t1.Start();
   t2.Start();
   _countdown.Wait();//如果_countdown.Signal()没达到指定次数,_countdown.Wait()将一直等待
   WriteLine("Both operations have been completed.");
   _countdown.Dispose();
  }
  static CountdownEvent _countdown = new CountdownEvent(2);
  static void PerformOperation(string message, int seconds)
  {
   Sleep(TimeSpan.FromSeconds(seconds));
   WriteLine(message);
   _countdown.Signal();//注册信号,减少计数
  }
4:Barrier类用于组织多个线程及时在某个时刻碰面,其提供了一个回调函数,每次线程调用了SignalAndWait方法后该回调函数会被执行。适用于多任务多阶段同步执行的场景。
static void Main(string[] args)
  {
   var t1 = new Thread(() => PlayMusic("任务1"));
   var t2 = new Thread(() => PlayMusic("任务2"));
    t1.Start();
    t2.Start();
    ReadLine();
  }
   //当有两个线程都执行完后就会执行回调。
  static Barrier _barrier = new Barrier(2,b => {
            WriteLine($"两个任务全部完成阶段: {b.CurrentPhaseNumber + 1}");
        });
  static void PlayMusic(string name)
  {
   for (int i = 1; i < 3; i++)
   {
    WriteLine($"{name} 执行阶段{i}");
    _barrier.SignalAndWait();
    }
  }
5:ReaderWriterLockSlim类允许多个线程同时读取与独占写。ReaderWriterLockSlim提供了四个方法来得到和释放读写锁:EnterReadLock(),ExitReadLock(),EnterWriteLock(),ExitWriteLock()。另外还提供了两个方法EnterUpgradeableReadLock()和ExitUpgradeableReadLock()两个方法来实现读写时的线程安全。通常情况下,当对全局list进行读写时的步骤为:
1 获得一个读取锁   
2 测试list是否包含item,如果是,则返回  
3 释放读取锁  
4 获得一个写入锁  
5 写入item到list中,释放写入锁。
但 是在步骤3、4之间,当另外一个线程可能偷偷修改List(比如说添加同样一个Item),ReaderWriterLockSlim通过提供第三种锁来 解决这个问题,这就是UpgradeableReadLock。一个可升级锁和ReadLock类似,只是它能够通过一个原子操作,被提升为WriteLock。使用方法如下:
1 调用EnterUpgradeableReadLock(进入可升级模式,可自动将读锁升级为写锁,无需切换)
2 读操作(测试list是否包含item,如果是,则调用ExitUpgradeableReadLock)
3 调用 EnterWriteLock
4 写操作(写入item到list中)
5 调用ExitWriteLock
6 其他读取的过程
7 调用ExitUpgradeableReadLock
可升级模式适用于线程通常读取受保护资源的内容,但在某些条件满足时可能需要写入的情况。使用可升级锁可以方便的从读锁中升级为写锁,而不需要进行切换,以增加损耗。
 
原文地址:https://www.cnblogs.com/zynNote/p/10524800.html