• <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>

            飯中淹的避難所~~~~~

            偶爾來避難的地方~

              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
              94 隨筆 :: 0 文章 :: 257 評論 :: 0 Trackbacks

             首先,我們來看一個例子。

              1 //    交互通道“沒有貨”狀態
              2 #define COMMUNICATIONCHANNEL_STATE_THINGSNOTEXISTS 0
              3 //    交互通道“有貨”狀態
              4 #define COMMUNICATIONCHANNEL_STATE_THINGSEXISTS 1
              5 //    交互通道結構
              6 struct CommunicationChannel
              7 {
              8     //    有貨沒貨的狀態
              9     volatile int iState;
             10     //    貨物:值0
             11     int iValue0;
             12     //    貨物:值1
             13     int iValue1;
             14 };
             15 //    線程參數
             16 struct ThreadParam
             17 {
             18     //    輸出通道
             19     CommunicationChannel * pOutputChannel;
             20     //    輸入通道
             21     CommunicationChannel * pInputChannel;
             22     //    減的值,用于制造奇數和偶數
             23     int iSubValue;
             24     //    值0的和
             25     int iSum0;
             26     //    值1的和
             27     int iSum1;
             28 };
             29 //    線程處理函數
             30 DWORD WINAPI ThreadProc( LPVOID lpParam )
             31 {
             32     //    取得參數
             33     ThreadParam * pParam = (ThreadParam*)lpParam;
             34     int iCounter = 0;
             35     bool bCountFinish = false;
             36     bool bCalcFinish = false;
             37 
             38     //    線程循環
             39     whiletrue )
             40     {
             41         //    向外輸出數值給另一個線程
             42         if!bCountFinish )
             43         {
             44             //    輸出通道是否是無貨狀態
             45             if( pParam->pOutputChannel->iState == COMMUNICATIONCHANNEL_STATE_THINGSNOTEXISTS )
             46             {
             47                 //    狀態滿足,輸出數字
             48                 if( iCounter < 10 )
             49                 {
             50                     //    頭10次,輸出一個序列
             51                     ++iCounter;
             52                     pParam->pOutputChannel->iValue0 = iCounter;
             53                     pParam->pOutputChannel->iValue1 = iCounter * 2 - pParam->iSubValue;
             54                 }
             55                 else
             56                 {
             57                     //    第11次,輸出0,不在進行向外輸出數字
             58                     pParam->pOutputChannel->iValue0 = 0;
             59                     pParam->pOutputChannel->iValue1 = 0;
             60                     bCountFinish = true;
             61                 }
             62                 //    修改輸出通道的狀態為有貨
             63                 pParam->pOutputChannel->iState = COMMUNICATIONCHANNEL_STATE_THINGSEXISTS;
             64             }
             65         }
             66         //    根據另一個線程輸入的數值進行計算
             67         if!bCalcFinish )
             68         {
             69             //    檢查輸入通道是否有貨
             70             if( pParam->pInputChannel->iState == COMMUNICATIONCHANNEL_STATE_THINGSEXISTS )
             71             {
             72                 //    狀態滿足
             73                 if( pParam->pInputChannel->iValue0 != 0 )
             74                 {
             75                     //    輸入不是0,就累加到和上
             76                     pParam->iSum0 += pParam->pInputChannel->iValue0;
             77                     pParam->iSum1 += pParam->pInputChannel->iValue1;
             78                     //    修改輸入通道為無貨
             79                     pParam->pInputChannel->iState = COMMUNICATIONCHANNEL_STATE_THINGSNOTEXISTS;
             80                 }
             81                 else
             82                 {
             83                     //    否則,結束掉計算輸入數值
             84                     //    因為另一個輸出0就表示不再有新貨到達
             85                     bCalcFinish = true;
             86                 }
             87             }
             88         }
             89         //    輸出和計算過程都結束,就跳出線程循環
             90         if( bCountFinish &&
             91             bCalcFinish )
             92             break;
             93     }
             94 
             95     return 0;
             96 }
             97 
             98 int _tmain(int argc, _TCHAR* argv[])
             99 {
            100     //    初始化兩個交互通道,用于A到B的信息傳送和B到A的信息傳送。
            101     struct CommunicationChannel A2BChannel = { COMMUNICATIONCHANNEL_STATE_THINGSNOTEXISTS, 00 };
            102     struct CommunicationChannel B2AChannel = { COMMUNICATIONCHANNEL_STATE_THINGSNOTEXISTS, 00 };
            103     //    初始化兩個線程參數,用于線程A和線程B
            104     struct ThreadParam ThreadAParam = { 
            105         &A2BChannel,
            106         &B2AChannel,
            107         0,
            108         0,
            109         0
            110     };
            111     struct ThreadParam ThreadBParam = { 
            112         &B2AChannel,
            113         &A2BChannel,
            114         1,
            115         0,
            116         0
            117     };
            118 
            119     //    創建線程A,B,并等待他們結束。
            120     DWORD dwId = 0;
            121     HANDLE hThreadA = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc, &ThreadAParam, 0&dwId );
            122     HANDLE hThreadB = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc, &ThreadBParam, 0&dwId );
            123     WaitForSingleObject( hThreadA, INFINITE );
            124     WaitForSingleObject( hThreadB, INFINITE );
            125     //    輸出線程A,B的計算結果。
            126     printf( "Thread A sum0 = %d sum1 = %d\n", ThreadAParam.iSum0, ThreadAParam.iSum1 );
            127     printf( "Thread B sum0 = %d sum1 = %d\n", ThreadBParam.iSum0, ThreadBParam.iSum1 );
            128 
            129     //    計算并輸出正確的結果,用于比較這個方法的計算結果是否正確。
            130     int iCorrectSum0 = 0;
            131     int iCorrectSum1A = 0;
            132     int iCorrectSum1B = 0;
            133     forint i = 1;i <= 10++i )
            134     {
            135         iCorrectSum0 += i;
            136         iCorrectSum1A += i * 2 - 1;
            137         iCorrectSum1B += i * 2;
            138     }
            139     printf( "Correct sum0 = %d sum1A = %d sum1B = %d\n", iCorrectSum0, iCorrectSum1A, iCorrectSum1B );
            140 
            141     return 0;
            142 }
            143 
            144 

            這個例子,使用第一篇里面的方法,實現了兩個線程雙向通信。

            線程處理函數里面進行的事情很簡單,就是:輸出通道沒貨,就放貨進去,輸入通道有貨,就取貨計算。

            在這個過程里,我們將線程A的輸出和線程B的計算結合起來看,稱為一個任務。

            這個任務,它是如下圖所示的過程進行處理的。





            紅色部分,是任務的主要處理部分。綠色的部分,則是隔離兩個線程中處理部分的重要因素。

            從圖上看,如果填充數據和使用數據的紅色部分在垂直方向有交錯,那么,就會導致線程同步問題。

            但是要那樣,需要狀態滿足要求在設置狀態的前面才行。上帝說,那是不可能的,不設置狀態,怎么可能達成狀態滿足要求。除非線程B穿越了。

            所以,使用這種方法,紅色部分永遠不會重合,也就實現了無鎖的線程通信!當然,只是在兩個線程間實現了。

            從單個通道來看,這種方法可以形象的看作一個線程在不斷的喂數據,另一個線程則在不斷的吃數據。這里就簡單的稱為“喂食”。

            喂食”是一種可用的方法,不過它也有缺點,比如得等另一個線程吃完才能喂新的食物;或者另一個線程得等第一個線程去喂才有東西吃。

            接下來,得挑戰點高難度的:突破喂食,以及兩個線程的限制。






            posted on 2010-05-06 14:49 飯中淹 閱讀(1649) 評論(3)  編輯 收藏 引用 所屬分類: 數據算法分析

            評論

            # re: 無鎖線程通信(2):例程與分析 2010-05-06 16:09 fcc
            在網上查了好久的資料,終于明白樓主的做法是不恰當的,在某些編譯環境下、某些編譯參數設置下可能是可行的,但并非嚴謹的。參見一篇著名的論文Threads Cannot Be Implemented As a Library。在此文中,舉出了兩個例子,1 Compilers may reorder memory operations 2 The hardware may reorder memory operations 。綜上,除非保證程序必定按源代碼一致的順序執行指令,否則樓主提供的這種多線程編程模式是不能嚴格保證安全的。以上拋磚引玉,僅供探討。  回復  更多評論
              

            # re: 無鎖線程通信(2):例程與分析 2010-05-06 16:34 shbooom
            就算不考慮編譯器優化,這個方法也是無效的。。。檢查和置位完全是兩個原子操作  回復  更多評論
              

            # re: 無鎖線程通信(2):例程與分析 2010-05-06 16:42 飯中淹
            @fcc
            確實是存在這種情況。
            @shbooom
            如果不考慮優化,還是可以用的,這個方法。

              回復  更多評論
              

            青青青国产精品国产精品久久久久| 久久综合九色欧美综合狠狠| 亚洲AV无码成人网站久久精品大| 伊人久久大香线蕉av不卡| 亚洲精品乱码久久久久久| 热久久这里只有精品| 色天使久久综合网天天| 久久天天躁狠狠躁夜夜avapp| 久久精品中文闷骚内射| 少妇久久久久久被弄到高潮| 国产V综合V亚洲欧美久久| 久久国产福利免费| 亚洲午夜久久久影院伊人| 久久久国产一区二区三区| 色狠狠久久AV五月综合| 人妻中文久久久久| 亚洲午夜久久久精品影院| 久久人人爽人人人人片av| 很黄很污的网站久久mimi色| 亚洲国产精品成人久久| 亚洲国产成人精品久久久国产成人一区二区三区综 | 国产激情久久久久影院老熟女| 人人妻久久人人澡人人爽人人精品| 久久99国产亚洲高清观看首页| 亚洲AV乱码久久精品蜜桃| 久久强奷乱码老熟女| 久久99精品久久久久久水蜜桃| 久久久噜噜噜久久熟女AA片| 亚洲色大成网站www久久九| 亚洲国产成人精品女人久久久 | 人妻精品久久久久中文字幕 | 亚洲国产成人久久笫一页| 成人精品一区二区久久| 99久久精品国产综合一区| 亚洲狠狠综合久久| 久久综合狠狠综合久久激情 | 欧美精品久久久久久久自慰| 亚洲精品美女久久久久99| 久久香蕉超碰97国产精品| 久久久婷婷五月亚洲97号色| 久久er99热精品一区二区|