• <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++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
              94 隨筆 :: 0 文章 :: 257 評論 :: 0 Trackbacks

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

              1 //    交互通道“沒有貨”狀態(tài)
              2 #define COMMUNICATIONCHANNEL_STATE_THINGSNOTEXISTS 0
              3 //    交互通道“有貨”狀態(tài)
              4 #define COMMUNICATIONCHANNEL_STATE_THINGSEXISTS 1
              5 //    交互通道結(jié)構(gòu)
              6 struct CommunicationChannel
              7 {
              8     //    有貨沒貨的狀態(tài)
              9     volatile int iState;
             10     //    貨物:值0
             11     int iValue0;
             12     //    貨物:值1
             13     int iValue1;
             14 };
             15 //    線程參數(shù)
             16 struct ThreadParam
             17 {
             18     //    輸出通道
             19     CommunicationChannel * pOutputChannel;
             20     //    輸入通道
             21     CommunicationChannel * pInputChannel;
             22     //    減的值,用于制造奇數(shù)和偶數(shù)
             23     int iSubValue;
             24     //    值0的和
             25     int iSum0;
             26     //    值1的和
             27     int iSum1;
             28 };
             29 //    線程處理函數(shù)
             30 DWORD WINAPI ThreadProc( LPVOID lpParam )
             31 {
             32     //    取得參數(shù)
             33     ThreadParam * pParam = (ThreadParam*)lpParam;
             34     int iCounter = 0;
             35     bool bCountFinish = false;
             36     bool bCalcFinish = false;
             37 
             38     //    線程循環(huán)
             39     whiletrue )
             40     {
             41         //    向外輸出數(shù)值給另一個線程
             42         if!bCountFinish )
             43         {
             44             //    輸出通道是否是無貨狀態(tài)
             45             if( pParam->pOutputChannel->iState == COMMUNICATIONCHANNEL_STATE_THINGSNOTEXISTS )
             46             {
             47                 //    狀態(tài)滿足,輸出數(shù)字
             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,不在進行向外輸出數(shù)字
             58                     pParam->pOutputChannel->iValue0 = 0;
             59                     pParam->pOutputChannel->iValue1 = 0;
             60                     bCountFinish = true;
             61                 }
             62                 //    修改輸出通道的狀態(tài)為有貨
             63                 pParam->pOutputChannel->iState = COMMUNICATIONCHANNEL_STATE_THINGSEXISTS;
             64             }
             65         }
             66         //    根據(jù)另一個線程輸入的數(shù)值進行計算
             67         if!bCalcFinish )
             68         {
             69             //    檢查輸入通道是否有貨
             70             if( pParam->pInputChannel->iState == COMMUNICATIONCHANNEL_STATE_THINGSEXISTS )
             71             {
             72                 //    狀態(tài)滿足
             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                     //    否則,結(jié)束掉計算輸入數(shù)值
             84                     //    因為另一個輸出0就表示不再有新貨到達
             85                     bCalcFinish = true;
             86                 }
             87             }
             88         }
             89         //    輸出和計算過程都結(jié)束,就跳出線程循環(huán)
             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     //    初始化兩個線程參數(shù),用于線程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     //    創(chuàng)建線程A,B,并等待他們結(jié)束。
            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的計算結(jié)果。
            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     //    計算并輸出正確的結(jié)果,用于比較這個方法的計算結(jié)果是否正確。
            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 

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

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

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

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





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

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

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

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

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

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

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






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

            評論

            # re: 無鎖線程通信(2):例程與分析 2010-05-06 16:09 fcc
            在網(wǎng)上查了好久的資料,終于明白樓主的做法是不恰當(dāng)?shù)模谀承┚幾g環(huán)境下、某些編譯參數(shù)設(shè)置下可能是可行的,但并非嚴(yán)謹(jǐn)?shù)摹⒁娨黄恼撐腡hreads Cannot Be Implemented As a Library。在此文中,舉出了兩個例子,1 Compilers may reorder memory operations 2 The hardware may reorder memory operations 。綜上,除非保證程序必定按源代碼一致的順序執(zhí)行指令,否則樓主提供的這種多線程編程模式是不能嚴(yán)格保證安全的。以上拋磚引玉,僅供探討。  回復(fù)  更多評論
              

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

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

              回復(fù)  更多評論
              

            日韩久久无码免费毛片软件| 久久久亚洲欧洲日产国码二区| 亚洲综合久久综合激情久久| 久久这里只有精品首页| 国产精品免费久久久久久久久| 久久久青草青青国产亚洲免观| 久久狠狠爱亚洲综合影院 | 久久综合给久久狠狠97色| avtt天堂网久久精品| 91超碰碰碰碰久久久久久综合| 人妻无码久久精品| 91视频国产91久久久| 热久久视久久精品18| 久久本道综合久久伊人| 久久国产精品99国产精| 中文字幕热久久久久久久| AAA级久久久精品无码区| 狠狠久久亚洲欧美专区| 麻豆精品久久久久久久99蜜桃| 久久亚洲综合色一区二区三区| 囯产精品久久久久久久久蜜桃| 久久久精品国产Sm最大网站| 精品午夜久久福利大片| 欧美黑人又粗又大久久久| 思思久久好好热精品国产| 久久久久亚洲AV无码去区首| 国产成人精品久久亚洲| 久久精品国产影库免费看| 国内精品久久人妻互换| 久久99精品国产自在现线小黄鸭| 人人狠狠综合久久亚洲高清| 一本久久a久久精品综合夜夜 | 久久这里只有精品18| 久久人爽人人爽人人片AV| 一本综合久久国产二区| 伊人久久五月天| 亚洲欧美国产精品专区久久| 久久成人精品| 亚洲欧洲久久av| 狠狠色婷婷久久一区二区| 99久久精品国产一区二区 |