国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > C# > 正文

深入多線程之:雙向信號(hào)與競(jìng)賽的用法分析

2020-01-24 03:19:46
字體:
供稿:網(wǎng)友

雙向信號(hào)和競(jìng)賽(Two-Way Signaling and Races)
 
Monitor.Pulse方法的一個(gè)重要特性是它是異步執(zhí)行的,這意味著調(diào)用pulse方法并不會(huì)阻塞自己等待Monitor.Pulse返回。如果任何一個(gè)線程在pulsed 對(duì)象上等待,它是不會(huì)阻塞的,換句話說,調(diào)用Monitor.Pulse對(duì)程序不會(huì)有什么作用,你可以認(rèn)為Monitor.Pulse方法被忽略了。
這樣Pulse提供了一個(gè)單向通信:一個(gè) pulsing線程悄悄的向一個(gè)waiting 線程發(fā)送信號(hào)。
Pulse并不會(huì)返回一個(gè)值來告訴你waiting線程是否收到信號(hào)。

但是有時(shí)候我們需要知道waiting線程是否受到信號(hào),例如下面的例子:

復(fù)制代碼 代碼如下:

class Race
    {
        static readonly object _locker = new object();
        static bool  _go;
        public static void MainThread()
        {
            new Thread(SaySomething).Start();
            for (int i = 0; i < 5; i++)
            {
                lock (_locker)
                {
                    _go = true;
                    Monitor.PulseAll(_locker); //通知等待的隊(duì)列
                }
            }
        }
        static void SaySomething()
        {
            for (int i = 0; i < 5; i++)
            {
                lock (_locker)
                {
                    while (!_go) Monitor.Wait(_locker); //如果_go 為false,那么開始阻塞。
                    _go = false;
                    Console.WriteLine("Wassup?");
                }
            }
        }
    }

期待的輸出:
Wassup?
Wassup?
Wassup?
Wassup?
Wassup?

實(shí)際的輸出:

Wassup? (線程等待)
 
在SaySomething方法中,for循環(huán)執(zhí)行到while,此時(shí)_go為false,所以Monitor.Wait開始等待。在MainThread中,for循環(huán)設(shè)置_go為true。然后PulseAll.但是PulseAll方法是異步的。
所以在SaySomething線程被喚醒前,mainThread中的for循環(huán)可能已經(jīng)執(zhí)行完畢。所以SaySomething方法中的第一個(gè)Wait線程收到消息詞是_go為true,所以往下執(zhí)行,再次將_go字段設(shè)置為false。輸出”Wassup?”,但是下次循環(huán)由于_go為false,所以需要再次wait.所以實(shí)際的輸出打印了一個(gè)Wassup,然后開始等待。
我們需要主線程在每一次迭代中如果worker仍然在執(zhí)行上一個(gè)任務(wù),那么主線程阻塞。等到worker執(zhí)行完畢,那么主線程恢復(fù)執(zhí)行,然后執(zhí)行迭代。

我們可以增加一個(gè)_ready 標(biāo)志,從而控制主線程在設(shè)置_go 標(biāo)志之前worker線程已經(jīng)ready了。也就是說主線程在設(shè)置_go之前,會(huì)等待worker完成任務(wù),然后等待worker將ready設(shè)為true,當(dāng)worker將ready設(shè)置為true后,通過pulse來通知主線程。
復(fù)制代碼 代碼如下:

class Race
    {
        static readonly object _locker = new object();
        static bool _ready, _go;
        public static void MainThread()
        {
            new Thread(SaySomething).Start();
            for (int i = 0; i < 5; i++)
            {
                lock (_locker)
                {
                    while (!_ready) Monitor.Wait(_locker); //如果worker的ready為false,則等待worker。
                    _ready = false; //重置標(biāo)志
                    _go = true;
                    Monitor.PulseAll(_locker);
                }
            }
        }
        static void SaySomething()
        {
            for (int i = 0; i < 5; i++)
            {
                lock (_locker)
                {
                    _ready = true; //將ready設(shè)置為true
                    Monitor.PulseAll(_locker); //通知主線程,worker已經(jīng)ready了,可以執(zhí)行任務(wù)了。
                    while (!_go) Monitor.Wait(_locker);
                    _go = false;
                    Console.WriteLine("Wassup?");
                }
            }
        }
    }

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 上杭县| 云龙县| 手游| 维西| 丽江市| 股票| 沙坪坝区| 濉溪县| 藁城市| 太原市| 张掖市| 礼泉县| 海晏县| 桃园县| 久治县| 温宿县| 牡丹江市| 互助| 天峨县| 莱州市| 汽车| 玉环县| 乌兰县| 浦东新区| 西城区| 哈巴河县| 平乡县| 全州县| 尉犁县| 安塞县| 铜陵市| 罗山县| 栾川县| 团风县| 天柱县| 淮滨县| 怀安县| 郁南县| 铜山县| 湖南省| 盐山县|