亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

細說.NET中的多線程(五使用信號量進行同步)

2019-11-14 13:50:01
字體:
來源:轉載
供稿:網友

上一節主要介紹了使用鎖進行同步,本節主要介紹使用信號量進行同步

使用EventWaitHandle信號量進行同步

EventWaitHandle主要用于實現信號燈機制。信號燈主要用于通知等待的線程。主要有兩種實現:AutoResetEvent和ManualResetEvent。

AutoResetEvent

AutoResetEvent從字面上理解是一個自動重置的時間。舉個例子,假設有很多人等在門外,AutoResetEvent更像一個十字旋轉門,每一次只允許一個人進入,進入之后門仍然是關閉狀態。

下面的例子演示了使用方式:

using System;using System.Threading;class BasicWaitHandle{    static EventWaitHandle _waitHandle = new AutoResetEvent(false);    static void Main()    {        for (int i = 0; i < 3; i++)            new Thread(Waiter).Start();        for (int i = 0; i < 3; i++)        {            Thread.Sleep(1000);                  // Pause for a second...            Console.WriteLine("通知下一個線程進入");            _waitHandle.Set();                    // Wake up the Waiter.        }        Console.ReadLine();    }    static void Waiter()    {        var threadId = Thread.CurrentThread.ManagedThreadId;        Console.WriteLine("線程 {0} 正在等待", threadId);        _waitHandle.WaitOne();                // 等待通知        Console.WriteLine("線程 {0} 得到通知,可以進入", threadId);    }}

  

雙向信號燈

某些情況下,如果你連續的多次使用Set方法通知工作線程,這個時候工作線程可能還沒有準備好接收信號,這樣的話后面的幾次Set通知可能會沒有效果。這種情況下,你需要讓主線程得到工作線程接收信息的通知再開始發送信息。你可能需要通過兩個信號燈實現這個功能。

示例代碼:

using System;using System.Threading;class TwoWaySignaling{    static EventWaitHandle _ready = new AutoResetEvent(false);    static EventWaitHandle _go = new AutoResetEvent(false);    static readonly object _locker = new object();    static string _message;    static void Main()    {        new Thread(Work).Start();        _ready.WaitOne();                  // 在工作線程準備接收信息之前需要一直等待        lock (_locker) _message = "床前明月光";        _go.Set();                         // 通知工作線程開始工作        _ready.WaitOne();        lock (_locker) _message = "疑是地上霜";        _go.Set();        _ready.WaitOne();        lock (_locker) _message = "結束";    // 告訴工作線程退出        _go.Set();        Console.ReadLine();    }    static void Work()    {        while (true)        {            _ready.Set();                          // 表示當前線程已經準備接收信號            _go.WaitOne();                         // 工作線程等待通知            lock (_locker)            {                if (_message == "結束") return;        // 優雅的退出~-~                Console.WriteLine(_message);            }        }    }}

生產消費隊列

生產消費隊列是多線程編程里常見的的需求,他的主要思路是:

  1. 一個隊列用來存放工作線程需要用到的數據
  2. 當新的任務加入隊列的時候,調用線程不需要等待工作結束
  3. 1個或多個工作線程在后臺獲取隊列中數據信息

示例代碼:

using System;using System.Threading;using System.Collections.Generic; class PRoducerConsumerQueue : IDisposable{  EventWaitHandle _wh = new AutoResetEvent (false);  Thread _worker;  readonly object _locker = new object();  Queue<string> _tasks = new Queue<string>();   public ProducerConsumerQueue()  {    _worker = new Thread (Work);    _worker.Start();  }   public void EnqueueTask (string task)  {    lock (_locker) _tasks.Enqueue (task);    _wh.Set();  }   public void Dispose()  {    EnqueueTask (null);     // Signal the consumer to exit.    _worker.Join();         // Wait for the consumer's thread to finish.    _wh.Close();            // Release any OS resources.  }   void Work()  {    while (true)    {      string task = null;      lock (_locker)        if (_tasks.Count > 0)        {          task = _tasks.Dequeue();          if (task == null) return;        }      if (task != null)      {        Console.WriteLine ("Performing task: " + task);        Thread.Sleep (1000);  // simulate work...      }      else        _wh.WaitOne();         // No more tasks - wait for a signal    }  }}

為了保證線程安全,我們使用lock來保護Queue<string>集合。我們也顯示的關閉了WaitHandle。

在.NET 4.0中,一個新的類BlockingCollection實現了類似生產者消費者隊列的功能。

ManualResetEvent

ManualResetEvent從字面上看是一個需要手動關閉的事件。舉個例子:假設有很多人等在門外,它像是一個普通的門,門開啟之后,所有等在門外的人都可以進來,當你關閉門之后,不再允許外面的人進來。

示例代碼:

using System;using System.Threading;class BasicWaitHandle{    static EventWaitHandle _waitHandle = new ManualResetEvent(false);    static void Main()    {        for (int i = 0; i < 3; i++)            new Thread(Waiter).Start();        Thread.Sleep(1000);                  // Pause for a second...        Console.WriteLine("門已打開,線程進入");        _waitHandle.Set();                    // Wake up the Waiter.        new Thread(Waiter).Start();        Thread.Sleep(2000);        _waitHandle.Reset();        Console.WriteLine("門已關閉,線程阻塞");        new Thread(Waiter).Start();        Console.ReadLine();    }    static void Waiter()    {        var threadId = Thread.CurrentThread.ManagedThreadId;        Console.WriteLine("線程 {0} 正在等待", threadId);        _waitHandle.WaitOne();                // 等待通知        Console.WriteLine("線程 {0} 得到通知,可以進入", threadId);    }}

ManualResetEvent可以在當前線程喚醒所有等待的線程,這一應用非常重要。

CountdownEvent

CountdownEvent的使用和ManualEvent正好相反,是多個線程共同喚醒一個線程。

示例代碼:

 

using System;using System.Threading;class CountDownTest{    static CountdownEvent _countdown = new CountdownEvent(3);    static void Main()    {        new Thread(SaySomething).Start("I am thread 1");        new Thread(SaySomething).Start("I am thread 2");        new Thread(SaySomething).Start("I am thread 3");        _countdown.Wait();   // 當前線程被阻塞,直到收到 _countdown發送的三次信號        Console.WriteLine("All threads have finished speaking!");        Console.ReadLine();    }    static void SaySomething(object thing)    {        Thread.Sleep(1000);        Console.WriteLine(thing);        _countdown.Signal();    }}

創建跨進程的EventWaitHandle

EventWaitHandle的構造方法允許創建一個命名的EventWaitHandle,來實現跨進程的信號量操作。名字只是一個簡單的字符串,只要保證不會跟其它進程的鎖沖突即可。

示例代碼:

EventWaitHandle wh = new EventWaitHandle(false, EventResetMode.AutoReset, "MyCompany.MyApp.SomeName");

  

如果兩個進程運行這段代碼,信號量會作用于兩個進程內所有的線程。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品高潮呻吟视频| 日韩av影视在线| 欧美午夜片欧美片在线观看| 91豆花精品一区| 激情av一区二区| 亚洲国产一区二区三区在线观看| 69av成年福利视频| 国内外成人免费激情在线视频网站| 欧美久久精品午夜青青大伊人| 91免费观看网站| 日韩av免费在线| 第一福利永久视频精品| 欧美日韩国产一区中文午夜| 亚洲免费电影在线观看| 欧美一级在线亚洲天堂| 亚洲成**性毛茸茸| 亚洲专区国产精品| 亚洲xxxx视频| 日韩精品久久久久久久玫瑰园| 国产精品视频yy9099| 久久人人爽亚洲精品天堂| 日韩在线视频中文字幕| 欧美一级免费看| 51视频国产精品一区二区| 亚洲精品成人久久| 欧美日韩加勒比精品一区| 欧美日韩不卡合集视频| 久久69精品久久久久久国产越南| 97人人做人人爱| 国产精品1区2区在线观看| 国产精品高潮呻吟久久av黑人| 日韩欧美在线网址| 国产日韩欧美自拍| 大胆人体色综合| 成人黄色在线播放| 日本精品一区二区三区在线播放视频| 麻豆精品精华液| 91久久国产精品91久久性色| 91色精品视频在线| 成人黄色在线播放| 亚洲韩国日本中文字幕| 俺去了亚洲欧美日韩| 久久99国产精品久久久久久久久| 久久久亚洲影院你懂的| 丝袜一区二区三区| 搡老女人一区二区三区视频tv| 国产精品99久久久久久久久| 日韩精品极品在线观看播放免费视频| 国产精品日韩在线| 国产精品27p| 日韩有码在线观看| 中文字幕日韩欧美在线视频| 一区二区三区视频免费| 国产欧美一区二区三区四区| 欧美精品videosex性欧美| 中国人与牲禽动交精品| 97香蕉久久夜色精品国产| 日韩风俗一区 二区| 亚洲天堂视频在线观看| 国产视频999| 国产免费一区二区三区在线能观看| 一本色道久久88精品综合| 丝袜情趣国产精品| 日韩在线中文字| 久久精品一偷一偷国产| 亚洲国产另类 国产精品国产免费| 精品人伦一区二区三区蜜桃网站| 色久欧美在线视频观看| 欧美激情免费视频| 欧美一级在线亚洲天堂| 国产精品精品久久久| 欧美肥老太性生活视频| 九九热精品视频在线播放| 精品国产欧美成人夜夜嗨| 成人黄色影片在线| 国产精品国产福利国产秒拍| 成人国产精品一区| 国产成人精品免高潮费视频| 欧美性猛交xxxxx水多| 久久久国产精品x99av| 97在线观看视频国产| 国产日韩欧美中文| 精品欧美一区二区三区| 一区二区三欧美| 亚洲嫩模很污视频| 亚洲欧美日韩中文视频| 伊人伊成久久人综合网小说| 国产日韩欧美中文在线播放| 疯狂蹂躏欧美一区二区精品| 欧美亚洲一级片| 一区二区亚洲欧洲国产日韩| 欧美激情性做爰免费视频| 疯狂欧美牲乱大交777| 久久免费在线观看| 国产日韩精品视频| 亚洲一区二区三区乱码aⅴ| 国产精品美女在线观看| 国产精品福利在线观看网址| 国内精品久久影院| 成人激情视频免费在线| 欧美激情视频在线观看| 久久久久久午夜| 色哟哟亚洲精品一区二区| 97在线视频观看| 91精品免费视频| 青青久久av北条麻妃海外网| 日韩最新中文字幕电影免费看| 欧美黑人xxxⅹ高潮交| 欧洲一区二区视频| 国产精品欧美久久久| 国产91|九色| 欧美最猛性xxxxx亚洲精品| 红桃av永久久久| 九九视频直播综合网| 最近中文字幕mv在线一区二区三区四区| 91精品国产自产在线老师啪| 一区二区三区 在线观看视| 亚洲xxxx妇黄裸体| 成人羞羞国产免费| 97不卡在线视频| 国产成人jvid在线播放| 日韩精品免费在线视频观看| 亚洲美女自拍视频| 精品性高朝久久久久久久| 日韩激情在线视频| 欧美性猛交xxxxx免费看| 欧美视频一区二区三区…| 亚洲第一视频网站| 精品视频中文字幕| 欧美成人午夜剧场免费观看| 精品亚洲aⅴ在线观看| 国产a∨精品一区二区三区不卡| 欧美小视频在线观看| 亚洲一区亚洲二区| 久久午夜a级毛片| 国产成人精品电影久久久| 久久精品免费电影| 欧美性猛交xxxx免费看久久久| 亚洲欧美三级在线| 日韩欧美精品网址| 91沈先生在线观看| 久久久久久国产精品| 国产精品色午夜在线观看| 日韩精品在线免费播放| 亚洲国产小视频在线观看| 国产裸体写真av一区二区| 日韩激情av在线免费观看| 国产视频亚洲视频| 亚洲精品456在线播放狼人| 欧美老女人性视频| 亚洲精品99久久久久中文字幕| 久久亚洲国产成人| 日韩美女免费线视频| 伊人伊成久久人综合网小说| 久久国产精彩视频| 九色精品美女在线| 日韩精品视频免费在线观看| 国产综合视频在线观看| 日韩高清免费在线| 国产福利成人在线| 久久久综合免费视频| 欧美在线视频在线播放完整版免费观看| 亚洲a一级视频| 国产精品日韩欧美大师|