小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

線程間的同步概述

 wtkc 2014-11-20

線程間的同步概述

1.前言

前面幾篇文章著重介紹了多線程的三種創(chuàng)建方式及多線程間的4種通信方式,并采用大量的實(shí)例演示,相信大家對線程的創(chuàng)建和使用有了一定的了解。若還不了解請復(fù)習(xí)下前面的文章,多動手寫代碼和調(diào)試,光看不練,假把式。

今天先請大家看看下面一個多線程程序,操作很簡單,就是創(chuàng)建9個線程,并輸出相應(yīng)的線程編號(即報(bào)數(shù))。主要代碼如下:

  1. //聲明線程處理函數(shù)  
  2. <strong><span style="color:#ff0000;">unsigned __stdcall</span></strong>ThreadFunc( void* pArguments);//工作線程函數(shù)  
  3. HANDLE m_handle[9];//線程句柄列表  
  4. CListBox m_List; //數(shù)據(jù)列表控件  
  5. /////////////////////////////////////////////////  
  6. int g_nCount= 0;//這個是<strong><span style="color:#ff0000;">全局變量</span></strong>,用于線程報(bào)數(shù)(計(jì)數(shù))  
  7. //演示開始:創(chuàng)建線程  
  8. void CThreadProblem1Dlg::OnBnClickedButton1()  
  9. {  
  10.       // TODO: 在此添加控件通知處理程序代碼  
  11.       GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);  
  12.       m_List.ResetContent();//清空列表  
  13.       g_nCount = 0; //重置報(bào)數(shù),  
  14.       SetDlgItemInt(IDC_EDIT_NUM,++m_nNum); //顯示操作的次數(shù)  
  15.       //創(chuàng)建多線程  
  16.       for (int i=0;i<9;i++)  
  17.       {  
  18.            m_handle[i] = (HANDLE)<strong><span style="color:#ff0000;">_beginthreadex</span></strong>(NULL,0, ThreadFunc,&m_List,0, NULL);   
  19.       }  
  20.       //WaitForMultipleObjects(10, handle, TRUE, INFINITE);  //在此處等待退出,將發(fā)現(xiàn)程序假死了。所以采用線程的方式等待  
  21.     _beginthreadex(NULL,0, WaitThread,<strong><span style="color:#ff0000;">this</span></strong>, 0, NULL);    //等待上述的個線程都退出  
  22. }  
  23. //工作線程函數(shù)  
  24. unsigned __stdcall ThreadFunc(void* pArguments)  
  25. {  
  26.       Sleep(100);//相關(guān)處理  
  27.       g_nCount++; //計(jì)數(shù)加  
  28.       CListBox *pList= (CListBox*)pArguments;  
  29.       CString str;  
  30.       str.Format("  子線程ID號為%4d 報(bào)數(shù)為:%d",GetCurrentThreadId(),g_nCount);  
  31.     pList->AddString(str);//輸出  
  32.       Sleep(100);//相關(guān)處理  
  33.       return 0;   
  34. }  
  35. //線程函數(shù):等待個演示線程都退出再使能開始按鈕  
  36. unsigned __stdcall WaitThread(void* pArguments)  
  37. {  
  38.       CThreadProblem1Dlg *pMainDlg= (CThreadProblem1Dlg *)pArguments;  
  39.       <strong><span style="color:#ff0000;">WaitForMultipleObjects</span></strong>(9,pMainDlg->m_handle,TRUE, INFINITE);  //等待所有線程都結(jié)束  
  40.       EnableWindow(GetDlgItem(AfxGetApp()->m_pMainWnd->m_hWnd,IDC_BUTTON1),TRUE);//使能開始按鈕  
  41.       return 0;  
  42. }  

當(dāng)運(yùn)行一次OnBnClickedButton1()函數(shù),將顯示下面的結(jié)果:

你一看,沒錯呀,就應(yīng)該是這樣的,沒有錯呀!多運(yùn)行幾次也是這樣的。但我要肯定的告訴你,上面的程序是有嚴(yán)重的問題,而運(yùn)行結(jié)果也欺騙了你。正是運(yùn)行結(jié)果大大蒙騙了你的理智和大腦。你發(fā)現(xiàn)問題了嗎?(提示:不是報(bào)數(shù)順序的問題)

正是該錯誤有隱蔽性,你很難從結(jié)果中發(fā)現(xiàn)問題,除非你運(yùn)氣特別好,一運(yùn)行就能重現(xiàn)問題,但作為程序員,你決不能僅靠運(yùn)氣,不可能你每次的運(yùn)氣都這么好。

多運(yùn)行幾次上面的程序,你有可能發(fā)現(xiàn)問題,現(xiàn)在我把該程序改進(jìn)下,使其具有自動識別錯誤的智能,你一眼就能發(fā)現(xiàn)問題的。

改進(jìn)點(diǎn):添加結(jié)果檢測功能,若正常,其線程的報(bào)數(shù)應(yīng)該為1-9,有可能順序有變,但總和為45=1+2+3+4+5+6+7+8+9。程序?qū)⒁恢毖h(huán)到程序退出。若不等于45就退出循環(huán),表示有問題,即讓程序一直運(yùn)行,直到有錯誤為止。前面的OnBnClickedButton1()函數(shù)和ThreadFunc()函數(shù)保存不變,WaitThread()函數(shù)添加一個判斷語句,改進(jìn)程序如下:

  1. //線程函數(shù):等待個演示線程都退出再使能開始按鈕  
  2. unsigned __stdcall WaitThread(void* pArguments)  
  3. {  
  4.       CThreadProblem1Dlg *pMainDlg= (CThreadProblem1Dlg *)pArguments;  
  5.       WaitForMultipleObjects(9, pMainDlg->m_handle, TRUE,INFINITE); //等待所有線程都結(jié)束  
  6.       EnableWindow(GetDlgItem(AfxGetApp()->m_pMainWnd->m_hWnd,IDC_BUTTON1),TRUE);//使能開始按鈕  
  7.      <span style="color:#ff0000;"><strong> if(pMainDlg->m_bAuto&& !pMainDlg->IsError())  
  8.       {//若自動使能,則繼續(xù)下輪操作  
  9.            pMainDlg->OnBnClickedButton1();  
  10.       }</strong></span>  
  11.       return 0;  
  12. }  
  13. //添加IsError()函數(shù),用以判斷結(jié)果是否正確。  
  14. // 自動判斷每次運(yùn)行結(jié)果是否正確  
  15. bool CThreadProblem1Dlg::IsError(void)  
  16. {  
  17.       int nValue[9]={0};  
  18.       int nResult = 0;  
  19.       CString szText;  
  20.       for(int i=0;i<9;i++)  
  21.       {//得到各個線程的報(bào)數(shù)  
  22.            m_List.GetText(i,szText);  
  23.         szText = szText.Right(1);  
  24.            nValue[i] = atoi(szText);  
  25.            nResult += nValue[i];  
  26.       }  
  27.       //判斷是否有相同的值出現(xiàn)  
  28.       if (nResult != <span style="color:#ff0000;"><strong>45</strong></span>)  
  29.       {//有錯誤  
  30.            return true;  
  31.       }  
  32.       return false;  
  33. }  

再運(yùn)行上面的程序,選中“自動判斷”,程序?qū)⒑芸觳煌5倪\(yùn)行,但很快將又停下來,運(yùn)行結(jié)果如下圖所示,有可能你的結(jié)果和我的不一樣,但類型差不多的。

工程源碼下載:http://download.csdn.net/detail/cbnotes/5015914

現(xiàn)在你發(fā)現(xiàn)問題了嗎?對了,報(bào)數(shù)出現(xiàn)相同數(shù)了(見上圖出現(xiàn)兩個“2”)。

你可能要問,怎么會這樣呢?

這就是多線程最容易出現(xiàn)的問題,也是多線程編程的難點(diǎn)和核心。再說說上面程序,創(chuàng)建了9個線程,這9個線程是同時(shí)運(yùn)行的(即并行運(yùn)行),它們都要修改變量全局g_nCountg_nCount++;),就有可能兩個或多個線程同時(shí)讀取到g_nCount,而當(dāng)前的g_nCount已經(jīng)被其它線程修改,即輸出的不是線程當(dāng)前的值。這和單線程的順序執(zhí)行是有很大不同的。

那有什么方法解決上面的問題嗎?當(dāng)然有,這就是在江湖中大名鼎鼎的線程同步技術(shù),而且系統(tǒng)提供了多種線程同步的技術(shù)/方法。

2.什么是同步

“同步”不是指平常所說的兩件事情同時(shí)進(jìn)行。它的目的是使多個線程之間協(xié)調(diào)工作,而且常常是避免兩個線程同時(shí)進(jìn)行某些操作,比如同時(shí)訪問同一個共享資源。一般來說,同步是通過暫時(shí)將會發(fā)生沖突操作的某個線程暫停執(zhí)行(稱為阻塞線程),然后等待不會沖突時(shí)再繼續(xù)執(zhí)行。

3.需要同步的情況

3.1、多個線程同時(shí)訪問同一對象時(shí)

MFC對象在對象級不是線程安全的,只有在類級才是。如:兩個線程可以安全地使用兩個不同的CString對象,但同時(shí)使用同一個CString對象就可能產(chǎn)生問題。如果必須使用同一個對象,那么應(yīng)該采取適當(dāng)?shù)耐交胧?/p>

3.2、多個線程之間需要協(xié)調(diào)運(yùn)行

例如,如果第二個線程需要等待第一個線程完成到某一步時(shí)才能運(yùn)行,那么該線程應(yīng)該暫時(shí)掛起以減少對CPU的占用時(shí)間,提高程序的執(zhí)行效率。當(dāng)?shù)谝粋€線程完成了相應(yīng)的步驟后,應(yīng)該發(fā)出某種信號來激活第二個線程。

4.Windows中的4種線程同步技術(shù)

4.1、Events(事件)——CEvent

作為標(biāo)志在線程之間傳遞信號。簡單地說,類似一個布爾型變量的開關(guān)作用。

4.2、Critical Sections(臨界段)——CCriticalSection

在進(jìn)程中作為關(guān)鍵字以獲得對共享資源的訪問

4.3、Mutexes(互斥量)——CMutex

與臨界段的工作方式相似,只是該對象可以用于多進(jìn)程中的線程同步,而不是用于單進(jìn)程中

4.4、Semaphores(信號量)——CSemaphore

在給定的限制條件下,允許多個進(jìn)程同時(shí)訪問共享資源

關(guān)于這四種同步方法/技術(shù)我將一個一個給大家介紹和實(shí)例演示,歡迎大家繼續(xù)關(guān)注。

=====================================================

轉(zhuǎn)載請標(biāo)明出處,謝謝。http://blog.csdn.net/cbNotes

=====================================================

 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多