程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 白話手動和自動信號量的區別

白話手動和自動信號量的區別

編輯:關於.NET

講到信號,就不得不講到3種涉眾:1.發信號者;2.傳信號者;3.眼巴巴的等 著收信號的。

(看官此時噓我了,書上可沒這麼講過,你瞎叨叨啥呢? )

打個比方,超級大樂透搖獎開始了,全國無數財迷(哦,謝特!打拼 音的壞處就是經常出現這種情況,把彩民打成財迷了)就是第3種人,眼巴巴的 等著最後的數字,在數字沒出爐前,盡管他們中有手心冒汗的,哈喇子吧嗒吧嗒 流的,眼睛紅了紫、紫了綠的,但他他們都有一個共同點,那就是死,也要死在 電視機前,決不挪動半步,“等”就一個字!涉眾的第2中就是電視 媒體了,它們負責傳遞實時的信息。第1種顯然就是超級大樂透搖獎現場樂。一 旦搖出大獎,那些等著的人有的抹了抹口水該干嗎干嗎去了,有的擦了擦汗睡覺 去了,中大獎的准備人間蒸發了,中小獎的准備連夜上大拍檔了,在農村沒啥消 遣的就抱老公摟老婆上炕了,看官,您貴干去了呀?

當然.WINDOWS裡信 號量是不少的,有用於進程內線程同步的、有由於進程間同步的、有臨界資源互 斥訪問同步的,今天,現在,咱只討論事件信號。先參考平台SDK裡的函數,僅 供參考,不看也罷。當然,給看官你帶來的損失也罷,哈哈!

The CreateEvent function creates or opens a named or unnamed event object.

HANDLE CreateEvent(
  LPSECURITY_ATTRIBUTES lpEventAttributes,
  BOOL bManualReset,
  BOOL bInitialState,
  LPCTSTR lpName
);

The SetEvent function sets the specified event object to the signaled state.

BOOL SetEvent(
  HANDLE hEvent
);

The ResetEvent function sets the specified event object to the nonsignaled state.

BOOL ResetEvent(
  HANDLE hEvent
);

The WaitForSingleObject function returns when the specified object is in the signaled state or the time-out interval elapses.

To enter an alertable wait state, use the WaitForSingleObjectEx function.To wait for multiple objects, use the WaitForMultipleObjects.

DWORD WaitForSingleObject(
  HANDLE hHandle,
  DWORD dwMilliseconds
);

以上四個函數是最基本的,面向過程的,事件信號控制函數。 在.NET裡,封裝出了ManualResetEvent、AutoResetEvent 兩個類,上面四個函 數就是這兩個類的底層實現。

仔細看雖然有手工和自動信號量兩個類, 其實對應CreateEvent函數只是第二個參數去TRUE還是FALSE的區別。

那 麼,手動和自動的是針對什麼而言的呢?實際上對信號狀態重置是由誰完成來區 別的。

手工信號量必須人為編程控制信號到初始狀態,自動信號量由操 作系統在把信號調度給等待線程中的任何一個線程(調度策略請參考操作系統核 心原理方面的書)之後立即自動把信號置為初始狀態。

那麼,什麼叫有 信號呢?比如搖獎結果出來後就是有信號了,所以有人沉默、有人悲傷、有歡呼 、有尖叫,在此之前,都稱為無信號狀態,那時大家不都在"等"嗎?

看官您又要問了,信號狀態重置又是什麼呢?就是把信號量狀態恢復到 初始狀態。

比如: 搖獎結果出來了,你以為地球人都知道了呀?錯、錯 、錯!如果你買了彩票突然飛去了墨西哥給人看感冒去了,墨西哥並不轉播偉大 的中國中央電視台,傻了吧?哪怕是你中了獎,你卻高興不起來,為啥?因為你 沒收到信號呀(打電話去廣電總局問問不就知道了)。這就等同於盡管信號發出 了,但其中的等待線程並沒有收到信號,這和沒發信號就是一樣的效果啦。如果 知道彩票搖獎結果,從網上找重播錄像吧,哈哈!

好了,廢話不說了, 調試以下兩段代碼就見分曉了:

ManualResetEvent

 

 1 using System;
 2 using System.Text;
 3 using System.Threading;
 4
 5 namespace ConsoleApplication1
 6 {
 7     class Program
 8     {
 9         static System.Threading.ManualResetEvent e = new System.Threading.ManualResetEvent(false);
10
11         static string resource = "";
12
13         static void Main(string[] args)
14         {
15             resource = "i am wzcheng";
16
17             new Thread(new ThreadStart(A)).Start();
18             new Thread(new ThreadStart(B)).Start();
19             new Thread(new ThreadStart(C)).Start();
20  
21             e.Set(); //發出信號,此時信號量狀態為有信號 態,上面三個線程得到運行
22
23              Thread.CurrentThread.Join(1000);
24
25             Console.WriteLine("重置信號量狀態按Y, 否則按N");
26
27             if ("N" == Console.ReadLine ().ToUpper())
28             {
29                 //此線程不會被阻塞,因為信號量有信號
30                 new Thread(new ThreadStart (D)).Start();
31             }
32             else
33             {
34
35                 e.Reset(); //此時信號量狀態為無信號 態
36
37                 //線程阻塞中
38                 new Thread(new ThreadStart (D)).Start();
39
40                 e.Set(); //發出信號,此時信號量狀態 為有信號態,上面的線程得到運行
41             }
42
43             Console.ReadLine();
44         }
45
46
47         public static void A()
48         {
49             e.WaitOne();
50             Console.WriteLine("對句子進行拼寫檢 查:{0}",resource );
51         }
52
53         public static void B()
54         {
55             e.WaitOne();
56             Console.WriteLine("對句子進行語法分 析:{0}", resource);
57         }
58
59         public static void C()
60         {
61             e.WaitOne();
62             Console.WriteLine("對句子進行文本處 理:{0}", resource);
63         }
64
65         public static void D()
66         {
67             e.WaitOne();
68             resource = "i am XXX";
69             Console.WriteLine("清空資源:{0}", resource);
70         }
71     }
72 }
73 

AutoResetEvent

using System;
using System.Text;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        static System.Threading.AutoResetEvent e = new System.Threading.AutoResetEvent(false);

        static string resource = "";

        static void Main(string[] args)
        {
            resource = "i am wzcheng";

            new Thread(new ThreadStart(A)).Start();
            new Thread(new ThreadStart(B)).Start();
            new Thread(new ThreadStart(C)).Start();

            e.Set();
            /*發出信號,此時信號量狀態為有信號態,上面三個線 程中隨機一個得到運行。
              因為三個線程等待的是自動信號量,所以在信號 量發出信號後,同等機會的三個線程被CPU
              挑選其中一個(這是WINDOWS操作系統調度策略, 此時忽略線程優先級)喚醒。
              但隨後信號量立即被自動恢復到初始的無信號狀 態,所以其余兩個線程無法運行。
             */

            //如果希 望其它的線程繼續得到運行,可以取消線程函數中被注釋掉的行 //e.Set();

            Console.ReadLine();
        }


        public static void A()
        {
            e.WaitOne();
            Console.WriteLine("對句子進行拼寫檢查:{0} ",resource );
            //e.Set();
        }

        public static void B()
        {
            e.WaitOne();
            Console.WriteLine("對句子進行語法分析:{0} ", resource);
            //e.Set();
        }

        public static void C()
        {
            e.WaitOne();
            Console.WriteLine("對句子進行文本處理:{0} ", resource);
            //e.Set();
        }

    }
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved