• <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)了無鎖的線程通信!當然,只是在兩個線程間實現(xiàn)了。

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

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

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






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

            評論

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

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

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

              回復(fù)  更多評論
              

            区亚洲欧美一级久久精品亚洲精品成人网久久久久| 国产成人综合久久精品红| 精品久久久久久无码人妻热 | 亚洲国产精品成人久久蜜臀 | 人妻丰满AV无码久久不卡| 国产免费久久精品99re丫y| 久久99精品久久久久久不卡| 99久久精品国产麻豆| 久久精品免费观看| 久久久久亚洲爆乳少妇无| 一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区 | 欧美大香线蕉线伊人久久| 色狠狠久久AV五月综合| 久久久久99精品成人片试看| 久久av免费天堂小草播放| 久久精品二区| 国产91久久精品一区二区| 国内精品久久国产大陆| 亚洲国产精品一区二区久久| 国产成人久久精品一区二区三区| 99re久久精品国产首页2020| 香蕉久久夜色精品国产小说| 日本亚洲色大成网站WWW久久| 丰满少妇高潮惨叫久久久| 国产精品久久久香蕉| 人妻久久久一区二区三区| 亚洲国产二区三区久久| 色综合久久久久综合99| 久久人人爽人人爽人人AV| 很黄很污的网站久久mimi色| 欧美黑人激情性久久| 国产69精品久久久久9999| 国产亚洲综合久久系列| 国产叼嘿久久精品久久| 久久久噜噜噜久久中文字幕色伊伊| 精品久久久久久无码中文字幕| 久久综合亚洲色HEZYO社区| 久久青青草原综合伊人| 国产美女久久久| 久久久久久久97| 久久久免费观成人影院|