• 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
    可升级模式适用于线程通常读取受保护资源的内容,但在某些条件满足时可能需要写入的情况。使用可升级锁可以方便的从读锁中升级为写锁,而不需要进行切换,以增加损耗。
     
  • 相关阅读:
    SDK Hello world(直接使用SDK封装)
    一个类有多个基类的内存布局
    写个测试程序看看磁盘映像文件中哪个扇区可以使用?
    在服务中以当前用户身份启动一个程序
    在类有成员变量的场景下, 按照虚表原理, 模拟虚函数实现
    pipe----管道
    Qt序列化格式分析(qint,QString)(非常简单好用)
    模拟QQ系统设置面板实现功能
    Qt持久性对象进行序列化(同时比较了MFC与Java的方法)
    使用srvany.exe将任何程序作为Windows服务运行
  • 原文地址:https://www.cnblogs.com/zynNote/p/10524800.html
Copyright © 2020-2023  润新知