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

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

            偶爾來(lái)避難的地方~

              C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
              94 隨筆 :: 0 文章 :: 257 評(píng)論 :: 0 Trackbacks

             首先,我們來(lái)看一個(gè)例子。

              1 //    交互通道“沒(méi)有貨”狀態(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     //    有貨沒(méi)貨的狀態(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ù)值給另一個(gè)線程
             42         if!bCountFinish )
             43         {
             44             //    輸出通道是否是無(wú)貨狀態(tài)
             45             if( pParam->pOutputChannel->iState == COMMUNICATIONCHANNEL_STATE_THINGSNOTEXISTS )
             46             {
             47                 //    狀態(tài)滿足,輸出數(shù)字
             48                 if( iCounter < 10 )
             49                 {
             50                     //    頭10次,輸出一個(gè)序列
             51                     ++iCounter;
             52                     pParam->pOutputChannel->iValue0 = iCounter;
             53                     pParam->pOutputChannel->iValue1 = iCounter * 2 - pParam->iSubValue;
             54                 }
             55                 else
             56                 {
             57                     //    第11次,輸出0,不在進(jìn)行向外輸出數(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ù)另一個(gè)線程輸入的數(shù)值進(jìn)行計(jì)算
             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                     //    修改輸入通道為無(wú)貨
             79                     pParam->pInputChannel->iState = COMMUNICATIONCHANNEL_STATE_THINGSNOTEXISTS;
             80                 }
             81                 else
             82                 {
             83                     //    否則,結(jié)束掉計(jì)算輸入數(shù)值
             84                     //    因?yàn)榱硪粋€(gè)輸出0就表示不再有新貨到達(dá)
             85                     bCalcFinish = true;
             86                 }
             87             }
             88         }
             89         //    輸出和計(jì)算過(guò)程都結(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     //    初始化兩個(gè)交互通道,用于A到B的信息傳送和B到A的信息傳送。
            101     struct CommunicationChannel A2BChannel = { COMMUNICATIONCHANNEL_STATE_THINGSNOTEXISTS, 00 };
            102     struct CommunicationChannel B2AChannel = { COMMUNICATIONCHANNEL_STATE_THINGSNOTEXISTS, 00 };
            103     //    初始化兩個(gè)線程參數(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的計(jì)算結(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     //    計(jì)算并輸出正確的結(jié)果,用于比較這個(gè)方法的計(jì)算結(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 

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

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

            在這個(gè)過(guò)程里,我們將線程A的輸出和線程B的計(jì)算結(jié)合起來(lái)看,稱為一個(gè)任務(wù)

            這個(gè)任務(wù),它是如下圖所示的過(guò)程進(jìn)行處理的。





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

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

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

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

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

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

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






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

            評(píng)論

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

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

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

              回復(fù)  更多評(píng)論
              

            久久免费国产精品一区二区| 国产精品综合久久第一页| 囯产精品久久久久久久久蜜桃| 一本色道久久88综合日韩精品 | 久久精品国内一区二区三区| 亚洲综合精品香蕉久久网97| 国产精品久久久久a影院| 国产精品无码久久综合 | 久久久av波多野一区二区| 狠狠人妻久久久久久综合| 99久久精品国产一区二区| 国产精品美女久久久网AV| 无码AV波多野结衣久久| 色欲综合久久躁天天躁| 久久久中文字幕| 亚洲国产精品18久久久久久| 久久99精品久久久久久噜噜 | 午夜欧美精品久久久久久久| 狠狠久久综合伊人不卡| 99久久人妻无码精品系列蜜桃| 久久久久久午夜精品| 国产一区二区精品久久岳| 久久99亚洲网美利坚合众国| 久久乐国产综合亚洲精品| 久久精品国产亚洲精品| 91精品国产色综久久| 久久精品成人免费网站| 久久精品天天中文字幕人妻| 2021国内精品久久久久久影院| 国产一区二区精品久久岳| 亚洲国产精品久久久久婷婷软件| 韩国免费A级毛片久久| 亚洲va久久久噜噜噜久久男同| 四虎久久影院| 少妇被又大又粗又爽毛片久久黑人| 日本免费一区二区久久人人澡| 久久久女人与动物群交毛片| 久久婷婷五月综合色奶水99啪| 色欲久久久天天天综合网精品| 少妇人妻88久久中文字幕| 久久99热只有频精品8|