天天看點

面試歸來4--多線程同步機制差別

佛說,彼岸花,開一千年,落一千年,花葉永不相見。情不為因果,緣注定生死。

1 程序的組成:虛拟的位址空間,代碼,系統資源。

  線程分類:使用者界面線程,主線程。舉例:CWinApp 就是一個使用者界面線程。

  線程間通信的方式有兩種:1 全局變量 2 自定義消息響應

  線程間同步的方式有四種:MFC提供的同步對象

                          1 臨界區 CCriticalSection

                          2 事件 CEvent

                          3 互斥量 CMutex

                          4 信号量 CSemaphore

1 使用場合:當多個線程 通路一個獨占性的共享資源

  使用方法:(1)定義CCriticalSection 的一個全局對象。 CCriticalSection  ;

            (2)在需要保護的代碼或資源前調用。

            critical_section.Lock();

            線程調用這個函數Lock()獲得臨界區對象。如果其他線程沒有占有這個臨界區對象,調用Lock()的線程獲得臨界區對象;否則

            調用Lock()的線程就被挂起,放入一個由系統維護的隊列,直到占有臨界區的線程結束為止。

            (3)通路臨界區完閉,

             critical_section.Unlock();

             再通俗一點講,就是線程A執行到critical_section.Lock();語句時,如果其它線程(B)正在執行critical_section.Lock();語句             後且critical_section. Unlock();語句前的語句時,線程A就會等待,直到線程B執行完critical_section. Unlock();語句                 ,線程A才會繼續執行。

2 使用場合:CEvent 支援事件。當事件是一個線程在某種情況下用來喚醒另外一個線程的同步對象。

  狀态:有信号和無信号

  分類:自動事件和人工事件。自動和人工的差別是:CEvent 的無信号狀态是由系統自動重置的還是有開發者調用函數實作的。

  1、CEvent(BOOL bInitiallyOwn=FALSE,

          BOOL bManualReset=FALSE,

          LPCTSTR lpszName=NULL,

          LPSECURITY_ATTRIBUTES lpsaAttribute=NULL);

   bInitiallyOwn:指定事件對象初始化狀态,TRUE為有信号,FALSE為無信号;

bManualReset:指定要建立的事件是屬于人工事件還是自動事件。TRUE為人工事件,FALSE為自動事件;

後兩個參數一般設為NULL,在此不作過多說明。

2、BOOL CEvent::SetEvent();

  将 CEvent 類對象的狀态設定為有信号狀态。如果事件是人工事件,則 CEvent 類對象保持為有信号狀态,直到調用成員函數ResetEvent()将 其重新設為無信号狀态時為止。如果CEvent 類對象為自動事件,則在SetEvent()将事件設定為有信号狀态後,CEvent 類對象由系統自動重置為無信号狀态。

如果該函數執行成功,則傳回非零值,否則傳回零。 3、BOOL CEvent::ResetEvent();

  該函數将事件的狀态設定為無信号狀态,并保持該狀态直至SetEvent()被調用時為止。由于自動事件是由系統自動重置,故自動事件不需

要調用該函數。如果該函數執行成功,傳回非零值,否則傳回零。

使用方法:線程(A),線程(B) 如果想先執行線程(A)在執行線程(B),那麼線上程(A)中代碼的最後調用 CEvent對象的SetEvent(),将事件對象置為有信号狀态,線上程(B)代碼的開始調用WaitForSingleObject() 那麼WaitForSingleObject()函數就可以一直監視CEvent對象一旦此對象為有信号狀态那麼線程(B)就可以執行了,進而實作了現場同步。

3 互斥對象和臨界區很像。CMutex

  差別:CMutex既可以在程序間使用,也可以在同一程序的各個線程間使用。

4 CSemaphore

  使用場合:允許多個線程同時通路一個共享資源,同時規定了同時通路這個共享資源的線程數目。

            其内部有一個計數器當有線程通路這個共享資源時 計數器自動減1 當計數器為0時就不運作其他線程在通路共享資源。

           (1)建立一個信号量對象

              CSemaphore semaphore(2,2);

              定義一個CSingleLock,CMutiLock;

              CSingleLock  singlelock(semaphore);

             要減小這個信号Semaphore的計數值,隻須調用CSingleLock對象的成員函數Lock()即可:

             SingleLock.Lock();

          同樣,通過調用UnLock()來釋放這個信号量,即:SingleLock.UnLock();

        示例代碼:http://www.vckbase.com/document/viewdoc/?id=762

繼續閱讀