資源描述:
《多線程編程之四——線程的同步》由會員上傳分享,免費在線閱讀,更多相關(guān)內(nèi)容在教育資源-天天文庫。
1、多線程編程之四——線程的同步八、線程的同步 雖然多線程能給我們帶來好處,但是也有不少問題需要解決。例如,對于像磁盤驅(qū)動器這樣獨占性系統(tǒng)資源,由于線程可以執(zhí)行進程的任何代碼段,且線程的運行是由系統(tǒng)調(diào)度自動完成的,具有一定的不確定性,因此就有可能出現(xiàn)兩個線程同時對磁盤驅(qū)動器進行操作,從而出現(xiàn)操作錯誤;又例如,對于銀行系統(tǒng)的計算機來說,可能使用一個線程來更新其用戶數(shù)據(jù)庫,而用另外一個線程來讀取數(shù)據(jù)庫以響應(yīng)儲戶的需要,極有可能讀數(shù)據(jù)庫的線程讀取的是未完全更新的數(shù)據(jù)庫,因為可能在讀的時候只有一部分數(shù)據(jù)被更新過。 使隸屬于同一進程的各線程協(xié)調(diào)一致地工作稱為線程的同步。MFC提供了多種同步對象,下面
2、我們只介紹最常用的四種:·臨界區(qū)(CCriticalSection)·事件(CEvent)·互斥量(CMutex)·信號量(CSemaphore) 通過這些類,我們可以比較容易地做到線程同步。A、使用CCriticalSection類 當多個線程訪問一個獨占性共享資源時,可以使用“臨界區(qū)”對象。任一時刻只有一個線程可以擁有臨界區(qū)對象,擁有臨界區(qū)的線程可以訪問被保護起來的資源或代碼段,其他希望進入臨界區(qū)的線程將被掛起等待,直到擁有臨界區(qū)的線程放棄臨界區(qū)時為止,這樣就保證了不會在同一時刻出現(xiàn)多個線程訪問共享資源。CCriticalSection類的用法非常簡單,步驟如下: 1.定義CCrit
3、icalSection類的一個全局對象(以使各個線程均能訪問),如CCriticalSectioncritical_section;2.在訪問需要保護的資源或代碼之前,調(diào)用CCriticalSection類的成員Lock()獲得臨界區(qū)對象:3.critical_section.Lock();在線程中調(diào)用該函數(shù)來使線程獲得它所請求的臨界區(qū)。如果此時沒有其它線程占有臨界區(qū)對象,則調(diào)用Lock()的線程獲得臨界區(qū);否則,線程將被掛起,并放入到一個系統(tǒng)隊列中等待,直到當前擁有臨界區(qū)的線程釋放了臨界區(qū)時為止。1.訪問臨界區(qū)完畢后,使用CCriticalSection的成員函數(shù)Unlock()來釋放臨
4、界區(qū):2.critical_section.Unlock();再通俗一點講,就是線程A執(zhí)行到critical_section.Lock();語句時,如果其它線程(B)正在執(zhí)行critical_section.Lock();語句后且critical_section.Unlock();語句前的語句時,線程A就會等待,直到線程B執(zhí)行完critical_section.Unlock();語句,線程A才會繼續(xù)執(zhí)行。下面再通過一個實例進行演示說明。例程8MultiThread81.建立一個基于對話框的工程MultiThread8,在對話框IDD_MULTITHREAD8_DIALOG中加入兩個按鈕和兩
5、個編輯框控件,兩個按鈕的ID分別為IDC_WRITEW和IDC_WRITED,標題分別為“寫‘W’”和“寫‘D’”;兩個編輯框的ID分別為IDC_W和IDC_D,屬性都選中Read-only;2.在MultiThread8Dlg.h文件中聲明兩個線程函數(shù):3.UINTWriteW(LPVOIDpParam);4.UINTWriteD(LPVOIDpParam);5.使用ClassWizard分別給IDC_W和IDC_D添加CEdit類變量m_ctrlW和m_ctrlD;6.在MultiThread8Dlg.cpp文件中添加如下內(nèi)容:為了文件中能夠正確使用同步類,在文件開頭添加:7.#inc
6、lude"afxmt.h"定義臨界區(qū)和一個字符數(shù)組,為了能夠在不同線程間使用,定義為全局變量:CCriticalSectioncritical_section;charg_Array[10];添加線程函數(shù):UINTWriteW(LPVOIDpParam){CEdit*pEdit=(CEdit*)pParam;pEdit->SetWindowText("");critical_section.Lock();//鎖定臨界區(qū),其它線程遇到critical_section.Lock();語句時要等待//直至執(zhí)行critical_section.Unlock();語句for(inti=0;i<10;
7、i++){g_Array[i]=''W'';pEdit->SetWindowText(g_Array);Sleep(1000);}critical_section.Unlock();return0;}UINTWriteD(LPVOIDpParam){CEdit*pEdit=(CEdit*)pParam;pEdit->SetWindowText("");critical_section.Lock();//鎖定臨界區(qū),其它線