青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-80  評論-22  文章-0  trackbacks-0

鎖的概念 原子操作 信號量  臨界區 線程同步

死鎖:

構成死鎖的條件四個,缺一不可

1一個線程只能單獨用一個資源

2正在使用的資源可以申請其他資源,同時自己的不會放開

3只有申請到其他資源,這個線程才會放開

4各個線程是循環狀態,就是每個線程要按照一定的順序申請,然后最后成為一個環。

原子操作:就是不可以有中斷的操作

信號量:與pv有關,表示資源的分配和釋放的情況。信號S,p則s-1,v則s+1。s表示可以使用的進程的數目。如果s>0表示還有進程可以使用,調用p則分配了資源,那么s-1,s<0表示沒有了資源可以使用,或者需要釋放的資源。 調用v操作,表示釋放的資源,因此s+1。調用P操作測試消息是否到達,調用V操作發送消息。

都是設計到同步和互斥概念的東西。

臨界區:就是在p(s)和v(s)之間的一種狀態。

線程同步:

 使隸屬于同一進程的各線程協調一致地工作稱為線程的同步

  • 臨界區(CCriticalSection)
  • 事件(CEvent)
  • 互斥量(CMutex)
  • 信號量(CSemaphore)

    A、使用 CCriticalSection 類

      當多個線程訪問一個獨占性共享資源時,可以使用“臨界區”對象。任一時刻只有一個線程可以擁有臨界區對象,擁有臨界區的線程可以訪問被保護起來的資源或代碼段,其他希望進入臨界區的線程將被掛起等待,直到擁有臨界區的線程放棄臨界區時為止,這樣就保證了不會在同一時刻出現多個線程訪問共享資源。

    CCriticalSection類的用法非常簡單,步驟如下:
     

    1. 定義CCriticalSection類的一個全局對象(以使各個線程均能訪問),如CCriticalSection critical_section;
    2. 在訪問需要保護的資源或代碼之前,調用CCriticalSection類的成員Lock()獲得臨界區對象:
      critical_section.Lock();
      在線程中調用該函數來使線程獲得它所請求的臨界區。如果此時沒有其它線程占有臨界區對象,則調用Lock()的線程獲得臨界區;否則,線程將被掛起,并放入到一個系統隊列中等待,直到當前擁有臨界區的線程釋放了臨界區時為止。
    3. 訪問臨界區完畢后,使用CCriticalSection的成員函數Unlock()來釋放臨界區:
      critical_section.Unlock();
      再通俗一點講,就是線程A執行到critical_section.Lock();語句時,如果其它線程(B)正在執行critical_section.Lock();語句后且critical_section. Unlock();語句前的語句時,線程A就會等待,直到線程B執行完critical_section. Unlock();語句,線程A才會繼續執行。

    下面再通過一個實例進行演示說明。


    例程8 MultiThread8

    1. 建立一個基于對話框的工程MultiThread8,在對話框IDD_MULTITHREAD8_DIALOG中加入兩個按鈕和兩個編輯框控件,兩個按鈕的ID分別為IDC_WRITEW和IDC_WRITED,標題分別為“寫‘W’”和“寫‘D’”;兩個編輯框的ID分別為IDC_W和IDC_D,屬性都選中Read-only;
    2. 在MultiThread8Dlg.h文件中聲明兩個線程函數:
      UINT WriteW(LPVOID pParam);
          UINT WriteD(LPVOID pParam);
    3. 使用ClassWizard分別給IDC_W和IDC_D添加CEdit類變量m_ctrlW和m_ctrlD;
    4. 在MultiThread8Dlg.cpp文件中添加如下內容:

      為了文件中能夠正確使用同步類,在文件開頭添加:
      #include "afxmt.h"
      定義臨界區和一個字符數組,為了能夠在不同線程間使用,定義為全局變量:
      CCriticalSection critical_section;
          char g_Array[10];
      添加線程函數:
      UINT WriteW(LPVOID pParam)
          {
          CEdit *pEdit=(CEdit*)pParam;
          pEdit->SetWindowText("");
          critical_section.Lock();
          //鎖定臨界區,其它線程遇到critical_section.Lock();語句時要等待
          //直至執行critical_section.Unlock();語句
          for(int i=0;i<10;i++)
          {
          g_Array[i]=''W'';
          pEdit->SetWindowText(g_Array);
          Sleep(1000);
          }
          critical_section.Unlock();
          return 0;
          }
          UINT WriteD(LPVOID pParam)
          {
          CEdit *pEdit=(CEdit*)pParam;
          pEdit->SetWindowText("");
          critical_section.Lock();
          //鎖定臨界區,其它線程遇到critical_section.Lock();語句時要等待
          //直至執行critical_section.Unlock();語句
          for(int i=0;i<10;i++)
          {
          g_Array[i]=''D'';
          pEdit->SetWindowText(g_Array);
          Sleep(1000);
          }
          critical_section.Unlock();
          return 0;
          }
    5. 分別雙擊按鈕IDC_WRITEW和IDC_WRITED,添加其響應函數:
      void CMultiThread8Dlg::OnWritew()
          {
          CWinThread *pWriteW=AfxBeginThread(WriteW,
          &m_ctrlW,
          THREAD_PRIORITY_NORMAL,
          0,
          CREATE_SUSPENDED);
          pWriteW->ResumeThread();
          }
          void CMultiThread8Dlg::OnWrited()
          {
          CWinThread *pWriteD=AfxBeginThread(WriteD,
          &m_ctrlD,
          THREAD_PRIORITY_NORMAL,
          0,
          CREATE_SUSPENDED);
          pWriteD->ResumeThread();
          }
      由于代碼較簡單,不再詳述。編譯、運行該例程,您可以連續點擊兩個按鈕,觀察體會臨界類的作用。

    B、使用 CEvent 類

      CEvent 類提供了對事件的支持。事件是一個允許一個線程在某種情況發生時,喚醒另外一個線程的同步對象。例如在某些網絡應用程序中,一個線程(記為A)負責監聽通訊端口,另外一個線程(記為B)負責更新用戶數據。通過使用CEvent 類,線程A可以通知線程B何時更新用戶數據。每一個CEvent 對象可以有兩種狀態:有信號狀態和無信號狀態。線程監視位于其中的CEvent 類對象的狀態,并在相應的時候采取相應的操作。
      在MFC中,CEvent 類對象有兩種類型:人工事件和自動事件。一個自動CEvent 對象在被至少一個線程釋放后會自動返回到無信號狀態;而人工事件對象獲得信號后,釋放可利用線程,但直到調用成員函數ReSetEvent()才將其設置為無信號狀態。在創建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()被調用時為止。由于自動事件是由系統自動重置,故自動事件不需要調用該函數。如果該函數執行成功,返回非零值,否則返回零。我們一般通過調用WaitForSingleObject函數來監視事件狀態。前面我們已經介紹了該函數。由于語言描述的原因,CEvent 類的理解確實有些難度,但您只要通過仔細玩味下面例程,多看幾遍就可理解。

    例程9 MultiThread9

    1. 建立一個基于對話框的工程MultiThread9,在對話框IDD_MULTITHREAD9_DIALOG中加入一個按鈕和兩個編輯框控件,按鈕的ID為IDC_WRITEW,標題為“寫‘W’”;兩個編輯框的ID分別為IDC_W和IDC_D,屬性都選中Read-only;
    2. 在MultiThread9Dlg.h文件中聲明兩個線程函數:
      UINT WriteW(LPVOID pParam);
          UINT WriteD(LPVOID pParam);
    3. 使用ClassWizard分別給IDC_W和IDC_D添加CEdit類變量m_ctrlW和m_ctrlD;
    4. 在MultiThread9Dlg.cpp文件中添加如下內容:

      為了文件中能夠正確使用同步類,在文件開頭添加

      #include "afxmt.h"
      定義事件對象和一個字符數組,為了能夠在不同線程間使用,定義為全局變量。
      CEvent eventWriteD;
          char g_Array[10];
      添加線程函數:
      UINT WriteW(LPVOID pParam)
          {
          CEdit *pEdit=(CEdit*)pParam;
          pEdit->SetWindowText("");
          for(int i=0;i<10;i++)
          {
          g_Array[i]=''W'';
          pEdit->SetWindowText(g_Array);
          Sleep(1000);
          }
          eventWriteD.SetEvent();
          return 0;
          }
          UINT WriteD(LPVOID pParam)
          {
          CEdit *pEdit=(CEdit*)pParam;
          pEdit->SetWindowText("");
          WaitForSingleObject(eventWriteD.m_hObject,INFINITE);
          for(int i=0;i<10;i++)
          {
          g_Array[i]=''D'';
          pEdit->SetWindowText(g_Array);
          Sleep(1000);
          }
          return 0;
          }
        仔細分析這兩個線程函數, 您就會正確理解CEvent 類。線程WriteD執行到 WaitForSingleObject(eventWriteD.m_hObject,INFINITE);處等待,直到事件eventWriteD為有信號該線程才往下執行,因為eventWriteD對象是自動事件,則當WaitForSingleObject()返回時,系統自動把eventWriteD對象重置為無信號狀態。
    5. 雙擊按鈕IDC_WRITEW,添加其響應函數:
      void CMultiThread9Dlg::OnWritew()
          {
          CWinThread *pWriteW=AfxBeginThread(WriteW,
          &m_ctrlW,
          THREAD_PRIORITY_NORMAL,
          0,
          CREATE_SUSPENDED);
          pWriteW->ResumeThread();
          CWinThread *pWriteD=AfxBeginThread(WriteD,
          &m_ctrlD,
          THREAD_PRIORITY_NORMAL,
          0,
          CREATE_SUSPENDED);
          pWriteD->ResumeThread();
          }
      編譯并運行程序,單擊“寫‘W’”按鈕,體會事件對象的作用。

    C、使用CMutex 類

      互斥對象與臨界區對象很像.互斥對象與臨界區對象的不同在于:互斥對象可以在進程間使用,而臨界區對象只能在同一進程的各線程間使用。當然,互斥對象也可以用于同一進程的各個線程間,但是在這種情況下,使用臨界區會更節省系統資源,更有效率。

    D、使用CSemaphore 類

      當需要一個計數器來限制可以使用某個線程的數目時,可以使用“信號量”對象。CSemaphore 類的對象保存了對當前訪問某一指定資源的線程的計數值,該計數值是當前還可以使用該資源的線程的數目。如果這個計數達到了零,則所有對這個CSemaphore 類對象所控制的資源的訪問嘗試都被放入到一個隊列中等待,直到超時或計數值不為零時為止。一個線程被釋放已訪問了被保護的資源時,計數值減1;一個線程完成了對被控共享資源的訪問時,計數值增1。這個被CSemaphore 類對象所控制的資源可以同時接受訪問的最大線程數在該對象的構建函數中指定。

    CSemaphore 類的構造函數原型及參數說明如下:

    CSemaphore (LONG lInitialCount=1,
    LONG lMaxCount=1,
    LPCTSTR pstrName=NULL,
    LPSECURITY_ATTRIBUTES lpsaAttributes=NULL);
    • lInitialCount:信號量對象的初始計數值,即可訪問線程數目的初始值;
    • lMaxCount:信號量對象計數值的最大值,該參數決定了同一時刻可訪問由信號量保護的資源的線程最大數目;
    • 后兩個參數在同一進程中使用一般為NULL,不作過多討論;

      在用CSemaphore 類的構造函數創建信號量對象時要同時指出允許的最大資源計數和當前可用資源計數。一般是將當前可用資源計數設置為最大資源計數,每增加一個線程對共享資源的訪問,當前可用資源計數就會減1,只要當前可用資源計數是大于0的,就可以發出信號量信號。但是當前可用計數減小到0時,則說明當前占用資源的線程數已經達到了所允許的最大數目,不能再允許其它線程的進入,此時的信號量信號將無法發出。線程在處理完共享資源后,應在離開的同時通過ReleaseSemaphore()函數將當前可用資源數加1。

    下面給出一個簡單實例來說明 CSemaphore 類的用法。

    例程10 MultiThread10

    1. 建立一個基于對話框的工程MultiThread10,在對話框IDD_MULTITHREAD10_DIALOG中加入一個按鈕和三個編輯框控件,按鈕的ID為IDC_START,標題為“同時寫‘A’、‘B’、‘C’”;三個編輯框的ID分別為IDC_A、IDC_B和IDC_C,屬性都選中Read-only;
    2. 在MultiThread10Dlg.h文件中聲明兩個線程函數:
      UINT WriteA(LPVOID pParam);
          UINT WriteB(LPVOID pParam);
          UINT WriteC(LPVOID pParam);
    3. 使用ClassWizard分別給IDC_A、IDC_B和IDC_C添加CEdit類變量m_ctrlA、m_ctrlB和m_ctrlC;
    4. 在MultiThread10Dlg.cpp文件中添加如下內容:

      為了文件中能夠正確使用同步類,在文件開頭添加:

      #include "afxmt.h"
      定義信號量對象和一個字符數組,為了能夠在不同線程間使用,定義為全局變量:
      CSemaphore semaphoreWrite(2,2); //資源最多訪問線程2個,當前可訪問線程數2個
          char g_Array[10];

      添加三個線程函數:

      UINT WriteA(LPVOID pParam)
          {
          CEdit *pEdit=(CEdit*)pParam;
          pEdit->SetWindowText("");
          WaitForSingleObject(semaphoreWrite.m_hObject,INFINITE);
          CString str;
          for(int i=0;i<10;i++)
          {
          pEdit->GetWindowText(str);
          g_Array[i]=''A'';
          str=str+g_Array[i];
          pEdit->SetWindowText(str);
          Sleep(1000);
          }
          ReleaseSemaphore(semaphoreWrite.m_hObject,1,NULL);
          return 0;
          }
          UINT WriteB(LPVOID pParam)
          {
          CEdit *pEdit=(CEdit*)pParam;
          pEdit->SetWindowText("");
          WaitForSingleObject(semaphoreWrite.m_hObject,INFINITE);
          CString str;
          for(int i=0;i<10;i++)
          {
          pEdit->GetWindowText(str);
          g_Array[i]=''B'';
          str=str+g_Array[i];
          pEdit->SetWindowText(str);
          Sleep(1000);
          }
          ReleaseSemaphore(semaphoreWrite.m_hObject,1,NULL);
          return 0;
          }
          UINT WriteC(LPVOID pParam)
          {
          CEdit *pEdit=(CEdit*)pParam;
          pEdit->SetWindowText("");
          WaitForSingleObject(semaphoreWrite.m_hObject,INFINITE);
          for(int i=0;i<10;i++)
          {
          g_Array[i]=''C'';
          pEdit->SetWindowText(g_Array);
          Sleep(1000);
          }
          ReleaseSemaphore(semaphoreWrite.m_hObject,1,NULL);
          return 0;
          }
      這三個線程函數不再多說。在信號量對象有信號的狀態下,線程執行到WaitForSingleObject語句處繼續執行,同時可用線程數減1;若線程執行到WaitForSingleObject語句時信號量對象無信號,線程就在這里等待,直到信號量對象有信號線程才往下執行。
    5. 雙擊按鈕IDC_START,添加其響應函數:
      void CMultiThread10Dlg::OnStart()
          {
          CWinThread *pWriteA=AfxBeginThread(WriteA,
          &m_ctrlA,
          THREAD_PRIORITY_NORMAL,
          0,
          CREATE_SUSPENDED);
          pWriteA->ResumeThread();
          CWinThread *pWriteB=AfxBeginThread(WriteB,
          &m_ctrlB,
          THREAD_PRIORITY_NORMAL,
          0,
          CREATE_SUSPENDED);
          pWriteB->ResumeThread();
          CWinThread *pWriteC=AfxBeginThread(WriteC,
          &m_ctrlC,
          THREAD_PRIORITY_NORMAL,
          0,
          CREATE_SUSPENDED);
          pWriteC->ResumeThread();
          }
  • posted on 2009-07-18 19:37 Bluesea 閱讀(752) 評論(1)  編輯 收藏 引用 所屬分類: C/C++

    評論:
    # re: windows下多線程問題[未登錄] 2012-05-22 11:15 | li
    Windows下的多線程同步問題設計的主要步驟有哪些  回復  更多評論
      
    青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美福利视频在线观看| 亚洲第一主播视频| 久久久久www| 欧美在线观看日本一区| 性做久久久久久免费观看欧美| 99精品国产在热久久婷婷| 亚洲卡通欧美制服中文| 一区二区av在线| 性高湖久久久久久久久| 久久婷婷综合激情| 欧美日韩国产91| 国产欧美一区二区三区视频| 国产一区二区丝袜高跟鞋图片 | 亚洲美女网站| 亚洲综合二区| 欧美成人午夜免费视在线看片| 欧美日韩另类字幕中文| 国产亚洲欧洲997久久综合| 亚洲第一在线综合网站| 在线亚洲欧美视频| 欧美资源在线| 亚洲精品男同| 亚洲视频1区2区| 久久久999国产| 国产精品免费福利| 亚洲国产裸拍裸体视频在线观看乱了中文| 亚洲精品国产欧美| 欧美在线免费视频| 亚洲三级免费电影| 亚洲伊人一本大道中文字幕| 久久国产精品久久精品国产| 欧美激情导航| 国内精品模特av私拍在线观看| 亚洲区在线播放| 亚洲欧美日韩国产综合精品二区| 国产精品va| 黄色成人在线网址| 亚洲欧美另类国产| 亚洲国产日韩在线| 欧美一区二区黄色| 欧美日韩在线综合| 黄色亚洲在线| 久久精品水蜜桃av综合天堂| 日韩视频免费在线| 欧美1区2区| 在线成人激情视频| 久久一区激情| 久久大逼视频| 国产在线不卡视频| 国产精品亚洲一区二区三区在线| 亚洲电影有码| 国产精品手机在线| 中文在线不卡| 亚洲精品看片| 久久综合伊人77777麻豆| 国产欧美视频一区二区三区| 宅男精品视频| 亚洲日本欧美天堂| 欧美激情第1页| 亚洲国产你懂的| 久久亚洲精品欧美| 久久爱www久久做| 国产女人aaa级久久久级| 亚洲一区二区三区久久| 亚洲精品免费观看| 欧美日本国产一区| 亚洲精品欧美精品| 亚洲福利视频网站| 欧美激情一区二区三区全黄 | 欧美在线播放| 亚洲夜间福利| 国产精品丝袜xxxxxxx| 久久精彩视频| 亚洲欧美在线一区二区| 国产精品久久久亚洲一区 | 亚洲在线视频| 亚洲欧美日本日韩| 国产美女精品视频免费观看| 销魂美女一区二区三区视频在线| 一区二区日韩精品| 国产精品日韩在线播放| 久久久久久久波多野高潮日日| 久久se精品一区精品二区| 伊人久久亚洲热| 亚洲激情一区| 国产精品日韩精品欧美在线| 久久天天综合| 欧美精品麻豆| 欧美专区在线观看| 巨乳诱惑日韩免费av| 宅男噜噜噜66一区二区| 亚洲免费视频在线观看| 在线观看视频一区二区| 亚洲精品中文字幕有码专区| 国产欧美日韩在线观看| 欧美大片在线观看一区二区| 欧美偷拍另类| 久久五月天婷婷| 欧美午夜不卡| 欧美激情精品久久久久久久变态| 国产精品成人一区二区| 欧美肥婆在线| 国产精品日韩一区| 亚洲三级色网| 亚洲成色777777在线观看影院| 亚洲美女电影在线| 狠狠色丁香婷婷综合影院| 99www免费人成精品| 在线成人激情| 欧美亚洲专区| 亚洲午夜小视频| 亚洲国产精品久久人人爱蜜臀| 国产精品高潮呻吟| 亚洲电影自拍| 伊人久久婷婷色综合98网| 亚洲一区日韩| 亚洲一区二区av电影| 久久影院午夜论| 欧美主播一区二区三区美女 久久精品人 | 欧美在线亚洲一区| 欧美日本国产精品| 欧美激情精品久久久久久大尺度 | 亚洲激情社区| 亚洲国产成人久久综合一区| 亚洲免费一在线| 亚洲美女av网站| 欧美福利一区| 欧美激情91| 亚洲风情亚aⅴ在线发布| 亚洲午夜日本在线观看| 一区二区三区欧美在线| 欧美成人午夜免费视在线看片| 久久久久久久久久久久久女国产乱| 国产精品看片你懂得| 99精品99| 亚洲一区精品在线| 国产精品久久久久天堂| 亚洲视频一二三| 亚洲欧美日韩一区二区| 国产精品va在线播放| 亚洲亚洲精品在线观看| 性色一区二区| 国产一区二区三区在线免费观看| 欧美一区三区二区在线观看| 久久www成人_看片免费不卡| 国产亚洲人成网站在线观看| 欧美在线观看日本一区| 欧美xx视频| 日韩一级大片在线| 欧美日韩日韩| 亚洲午夜精品一区二区三区他趣| 性欧美大战久久久久久久久| 国产精品青草久久| 欧美中文字幕久久| 欧美v日韩v国产v| 亚洲精品美女在线观看| 欧美激情自拍| 亚洲性感激情| 老司机凹凸av亚洲导航| 亚洲国产一区二区三区高清 | 在线精品观看| 欧美成人一二三| 一区二区三区免费网站| 久久久久久久久久久久久女国产乱 | 欧美在线播放| 欧美凹凸一区二区三区视频| 亚洲精品视频一区二区三区| 亚洲精品久久久久久久久久久久| 亚洲小视频在线观看| 国产精品欧美日韩一区| 久久亚洲图片| 一本大道久久a久久综合婷婷| 欧美影院在线播放| 在线精品国产成人综合| 欧美日韩在线观看视频| 欧美一区二区在线视频| 亚洲肉体裸体xxxx137| 久久久久久国产精品mv| 一区二区三区产品免费精品久久75 | 亚洲第一黄色网| 亚洲欧美第一页| 在线观看不卡av| 欧美日韩精品免费观看视频完整| 亚洲欧美日韩国产综合在线| 欧美顶级大胆免费视频| 翔田千里一区二区| 一本到12不卡视频在线dvd| 国产午夜亚洲精品理论片色戒| 欧美国产另类| 久久久综合香蕉尹人综合网| 一区二区三区久久精品| 亚洲高清影视| 久久综合影视| 欧美一级精品大片| 亚洲看片免费| 亚洲成人原创| 在线成人激情黄色| 国内精品久久久久影院色| 国产精品一区二区三区乱码| 欧美激情黄色片|