国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

并發(fā)編程 --- 信號量線程同步

這篇具有很好參考價(jià)值的文章主要介紹了并發(fā)編程 --- 信號量線程同步。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

引言

上文編碼技巧 --- 同步鎖對象的選定中,提到了在C#中,讓線程同步有兩種方式:

  • 鎖(lock、Monitor等)
  • 信號量(EventWaitHandle、Semaphore、Mutex)

加鎖是最常用的線程同步的方法,就不再討論,本篇主要討論使用信號量同步線程。

WaitHandle介紹

實(shí)際上,再C#中 EventWaitHandle 、 Semaphore 、 Mutex 都是抽象類 WaitHandle 的派生類,它提供了一組等待信號的方法和屬性。如下圖:

主要包含靜態(tài)方法 SignalAndWait(),WaitAll(),WaitAny()及一個(gè)虛方法WaitOne()。下面介紹一個(gè)這幾個(gè)方法。

介紹這些方法之前,先簡單介紹一下 WaitHandle 的派生類 EventWaitHandle,該派生類有兩個(gè)實(shí)現(xiàn)類 AutoResetEventManualResetEvent,其方法列表如下:

重點(diǎn)說一下,Set()Reset():

  • Set()方法設(shè)置事件為有信號狀態(tài):當(dāng)調(diào)用 Set() 時(shí),它將被設(shè)置為終止?fàn)顟B(tài),并允許一個(gè)或多個(gè)等待該事件的線程繼續(xù)執(zhí)行。
  • Reset()方法設(shè)置事件為無信號狀態(tài):當(dāng)調(diào)用 Reset() 時(shí),它將被設(shè)置為非終止?fàn)顟B(tài),所有想要等待該事件的線程都將被阻塞,直到調(diào)用 Set() 方法使其變?yōu)榻K止?fàn)顟B(tài)。

注意:這里的有信號,無信號的意思類似于紅綠燈,有信號你才能夠通行,對于線程來說,有信號意味著可以接著往下運(yùn)行,無信號則阻塞等待信號。

接下來的代碼段演示皆使用 AutoResetEvent 進(jìn)行演示。

SignalAndWait()

當(dāng)調(diào)用 WaitHandle 的靜態(tài)方法 SignalAndWait() 時(shí),會使得當(dāng)前線程等待一個(gè) WaitHandle 對象的信號,同時(shí)設(shè)置另一個(gè) WaitHandle 對象為有信號狀態(tài)。當(dāng)?shù)谝粋€(gè) WaitHandle 對象收到信號時(shí),當(dāng)前線程繼續(xù)執(zhí)行,同時(shí)第二個(gè) WaitHandle 對象變?yōu)闊o信號狀態(tài)。

static AutoResetEvent event1 = new AutoResetEvent(false);
static AutoResetEvent event2 = new AutoResetEvent(false);

static void Main(string[] args)
{
    Thread t1 = new Thread(new ThreadStart(Worker1));
    Thread t2 = new Thread(new ThreadStart(Worker2));

    t1.Start();
    t2.Start();

    Console.ReadLine();
}

static void Worker1()
{
    Console.WriteLine("線程1開始執(zhí)行……");

    event1.WaitOne(); // 等待事件1的發(fā)生

    Console.WriteLine("線程1收到事件1的信號,繼續(xù)執(zhí)行……");

    WaitHandle.SignalAndWait(event1, event2); // 發(fā)送事件2的信號并等待事件2的發(fā)生

    Console.WriteLine("線程1收到事件2的信號,繼續(xù)執(zhí)行……");
}

static void Worker2()
{
    Console.WriteLine("線程2開始執(zhí)行……");

    Thread.Sleep(2000); // 模擬線程2的執(zhí)行時(shí)間

    Console.WriteLine("線程2發(fā)出事件1的信號……");

    event1.Set(); // 發(fā)送事件1的信號

    Thread.Sleep(2000); // 模擬線程2的執(zhí)行時(shí)間

    Console.WriteLine("線程2發(fā)出事件2的信號……");

    WaitHandle.SignalAndWait(event2, event1); // 發(fā)送事件1的信號并等待事件1的發(fā)生

    Console.WriteLine("線程2收到事件1的信號,繼續(xù)執(zhí)行……");
}

輸出:

線程1開始執(zhí)行……
線程2開始執(zhí)行……
線程2發(fā)出事件1的信號……
線程1收到事件1的信號,繼續(xù)執(zhí)行……
線程2發(fā)出事件2的信號……
線程2收到事件1的信號,繼續(xù)執(zhí)行……
線程1收到事件2的信號,繼續(xù)執(zhí)行……

WaitAll()

當(dāng)調(diào)用 WaitHandle 的靜態(tài)方法 WaitAll() 時(shí),它可以等待多個(gè)WaitHandle對象的信號,直到所有對象都收到信號或等待超時(shí)。

static AutoResetEvent[] events = new AutoResetEvent[3]
{
    new AutoResetEvent(false),
    new AutoResetEvent(false),
    new AutoResetEvent(false)
};

static void Main(string[] args)
{
    Thread t1 = new Thread(new ThreadStart(Worker1));
    Thread t2 = new Thread(new ThreadStart(Worker2));

    t1.Start();
    t2.Start();

    Console.ReadLine();
}

static void Worker1()
{
    Console.WriteLine("線程1開始執(zhí)行……");

    WaitHandle.WaitAll(events); // 等待所有事件的發(fā)生

    Console.WriteLine("線程1收到所有事件的信號,繼續(xù)執(zhí)行……");
}

static void Worker2()
{
    Console.WriteLine("線程2開始執(zhí)行……");

    Thread.Sleep(2000); // 模擬線程2的執(zhí)行時(shí)間

    Console.WriteLine("線程2發(fā)出事件1的信號……");

    events[0].Set(); // 發(fā)送事件1的信號

    Thread.Sleep(2000); // 模擬線程2的執(zhí)行時(shí)間

    Console.WriteLine("線程2發(fā)出事件2的信號……");

    events[1].Set(); // 發(fā)送事件2的信號

    Thread.Sleep(2000); // 模擬線程2的執(zhí)行時(shí)間

    Console.WriteLine("線程2發(fā)出事件3的信號……");

    events[2].Set(); // 發(fā)送事件3的信號
}

輸出:

線程1開始執(zhí)行……
線程2開始執(zhí)行……
線程2發(fā)出事件1的信號……
線程2發(fā)出事件2的信號……
線程2發(fā)出事件3的信號……
線程1收到所有事件的信號,繼續(xù)執(zhí)行……

WaitAny()

當(dāng)調(diào)用 WaitHandle 的靜態(tài)方法 WaitAny() 時(shí),它可以等待多個(gè)WaitHandle對象中的任意一個(gè)對象收到信號,直到有一個(gè)對象收到信號或等待超時(shí)。

static AutoResetEvent[] events = new AutoResetEvent[3]
{
    new AutoResetEvent(false),
    new AutoResetEvent(false),
    new AutoResetEvent(false)
};

static void Main(string[] args)
{
    Thread t1 = new Thread(new ThreadStart(Worker1));
    Thread t2 = new Thread(new ThreadStart(Worker2));

    t1.Start();
    t2.Start();

    Console.ReadLine();
}

static void Worker1()
{
    Console.WriteLine("線程1開始執(zhí)行……");

    WaitHandle.WaitAny(events); // 等待任意事件的發(fā)生

    Console.WriteLine("線程1收到任意事件的信號,繼續(xù)執(zhí)行……");
}

static void Worker2()
{
    Console.WriteLine("線程2開始執(zhí)行……");

    var randomIndex = new Random().Next(0, 2);

    Console.WriteLine("線程2發(fā)出任意一個(gè)事件的信號……");

    events[randomIndex].Set(); //發(fā)送任意一個(gè)事件的信號
}

輸出:

線程1開始執(zhí)行……
線程2開始執(zhí)行……
線程2發(fā)出任意一個(gè)事件的信號……
線程1收到任意事件的信號,繼續(xù)執(zhí)行……

WaitOne()

WaitOne()方法上文中其實(shí)已經(jīng)用到了,它就表示阻塞當(dāng)前線程,等待當(dāng)前 WaitHandle 對象收到信號,直到對象收到信號或等待超時(shí)。如果WaitHandle對象收到信號,WaitOne()方法返回true,否則返回false。使用簡單就不在貼代碼段。

派生類的異同

上面已經(jīng)提到了EventWaitHandle 、 Semaphore 、 Mutex 都是抽象類 WaitHandle 的派生類,它們的作用類似,但在使用和實(shí)現(xiàn)上有一些不同。下面我們來簡單介紹下它們的異同點(diǎn)。

  1. EventWaitHandle:

    EventWaitHandle 有兩種類型:AutoResetEventManualResetEvent。它們的區(qū)別在于AutoResetEvent 在有信號時(shí)只通知一個(gè)等待線程,而 ManualResetEvent 在有信號時(shí)通知所有等待線程。
    兩者設(shè)置為終止?fàn)顟B(tài)的方式都是調(diào)用 Set() 方法。

  2. Semaphore

    Semaphore 可以用于多個(gè)線程之間的資源控制。Semaphore 可以控制同時(shí)訪問共享資源的線程數(shù)量。設(shè)置為終止?fàn)顟B(tài)的方式是調(diào)用 Release() 方法。

  3. Mutex

    Mutex 可以用于多個(gè)線程之間的互斥訪問共享資源。Mutex 可以保證同一時(shí)間只有一個(gè)線程可以訪問共享資源。設(shè)置為終止?fàn)顟B(tài)的方式是調(diào)用 ReleaseMutex() 方法。文章來源地址http://www.zghlxwxcb.cn/news/detail-576170.html

到了這里,關(guān)于并發(fā)編程 --- 信號量線程同步的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包