情景一中,我主要介绍了用于解决资源争用时各种方式的区别,本篇文章我们将进一步介绍线程同步的第二种场景。

 

 情景二:数量有限,先到先得

 

  情景简介:与情景一类似,但是这次茅坑的数量不只一个。如果有需求的人数少于茅坑数量,那一切都很和谐。但是人数超过茅坑数量的时候该怎么办?多个人占用一个坑?

  解决办法:当所有茅坑都客满的时候,其他人必须乖乖等在外面,只有当有人从里面出来的时候,下一个人才能进去。

  问题抽象:当某一资源同一时刻允许一定数量的线程使用的时候,需要有个机制来阻塞多余的线程,直到资源再次变得可用。

  线程同步方案:Semaphore、SemaphoreSlim

  方案特性:限量供应;除所有者外,其他人无条件等待;先到先得(谁先进茅坑,谁先用,没有先后顺序

 

  各方案间的区别

  Semaphore 的中文名称叫信号量,在学操作系统的时候肯定都会讲到。而扯到信号量,最常拿来举的就是生产者与消费者的例子。与上一篇一样,我不会在这里重复介绍一些网上多的是的内容,大家如果有兴趣,可以自己去找度娘、必硬或谷哥。

  在继续阅读前,请确保你已经对用户模式构造、内核模式构造和混合模式构造有所了解,如果尚未了解,建议您先阅读情景一中相关章节。

 

内核模式(kernal-mode)

  Semaphore 通过在构造函数中传入容器大小来限制一次性允许访问的线程数量。与情景一介绍中的 Mutex 一样属于内核模式,而且都拥有同一个祖宗:WaitHandle。但是与 Mutex 不一样的是,通过线程一获取的所有权,可以由线程二来释放。下面的写法是完全合法的。

    Task.Factory.StartNew(() =>
    {
        //类似于消费者
        semaphore.WaitOne();
        Thread.Sleep(5000);
    });
 
    Thread.Sleep(1000);
    Task.Factory.StartNew(() =>
    {
        //类似于生产者
        semaphore.Release();
    });

 

  优点:提供数量限制的能力,可以跨进程使用。

    //进程一
    Semaphore s = new Semaphore(1, 1, "myname", out creaded);
     
    //进程二
    Semaphore s = Semaphore.OpenExisting("myname");

  缺点:速度慢于用户模式、混合模式构造,稍快于 mutex。

 

 

混合模式(hybrid-mode)

  SemaphoreSlim 是 .Net 4.0 时引进的一个新类型,使用方式上类似 Semaphore,是轻量级的 Semaphore。不允许跨进程使用。

  优点:提供数量限制的能力;速度快,优于 Semaphore。

  缺点:不能跨进程使用。

 

总 结

  本篇文章介绍的方法主要用于解决资源有限(数量大于一)时线程同步的问题。如果资源唯一,那利用 Semaphore s = new Semaphore(1,1) 的效果与创建一个 Mutex 的效果实际是一致的。而此时的 Semaphore 会有一个新名称叫 Binary Semaphore (二元信号量)。

 

  那什么时候该使用 Semaphore, 什么时候使用 Mutex? 

  记住本系列强调的情景!如果用于资源争用,请使用 Mutex;如果用于限量使用请使用 Semaphore。

 

  本文来自《C# 基础回顾: 线程同步的情景之二

posted on 2014-10-25 18:36  stg609  阅读(1290)  评论(0编辑  收藏  举报
分享按钮