• <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
            如果不考慮優化,還是可以用的,這個方法。

              回復  更多評論
              

            免费精品99久久国产综合精品| 亚洲精品无码久久不卡| 久久亚洲欧美国产精品| 中文字幕热久久久久久久| 久久久亚洲欧洲日产国码二区| 久久福利青草精品资源站免费| 99久久人妻无码精品系列蜜桃| 91精品国产色综久久| 亚洲&#228;v永久无码精品天堂久久| 亚洲国产精品成人久久蜜臀| 久久久精品人妻一区二区三区蜜桃| 久久91精品国产91久久麻豆| 久久综合伊人77777麻豆| 色狠狠久久AV五月综合| 亚洲国产精品无码久久久久久曰 | 久久国产热精品波多野结衣AV| 精品一区二区久久| 亚洲乱码精品久久久久..| 久久久久九九精品影院| 99精品久久久久中文字幕| 亚洲国产精品一区二区三区久久 | 久久久久亚洲av毛片大| 国产亚洲精品自在久久| 久久国内免费视频| 久久国产精品波多野结衣AV| 久久天天躁狠狠躁夜夜网站| 久久只有这里有精品4| 色偷偷91久久综合噜噜噜噜| 国产福利电影一区二区三区久久久久成人精品综合 | 精品国产一区二区三区久久久狼 | 欧美日韩成人精品久久久免费看 | 久久影院综合精品| 久久国语露脸国产精品电影| 色综合久久88色综合天天 | 国内精品久久久久影院网站 | 99精品久久精品一区二区| 亚洲中文字幕无码久久综合网 | 久久久久久久91精品免费观看| 欧美麻豆久久久久久中文| 亚洲欧美国产日韩综合久久| 日本精品久久久久影院日本 |