• <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>
            隨筆 - 132  文章 - 51  trackbacks - 0
            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            常用鏈接

            留言簿(7)

            隨筆分類

            隨筆檔案

            文章分類

            文章檔案

            cocos2d-x

            OGRE

            OPenGL

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            多個線程操作相同的數據時,一般是需要按順序訪問的,否則會引導數據錯亂,無法控制數據,變成隨機變量。為解決這個問題,就需要引入互斥變量,讓每個線程都按順序地訪問變量。這樣就需要使用EnterCriticalSection和LeaveCriticalSection函數

            有人比如的很形象:
            就像上廁所:
            門鎖了,就等著,等到別人出來了,進去鎖上,然后該干什么干什么,干完了,把門打開

            門沒鎖,就進去,鎖上,然后該干什么干什么,干完了,把門打開

            --------------------------------------------------
            多線程中用來確保同一時刻只有一個線程操作被保護的數據

            InitializeCriticalSection(&cs);//初始化臨界區
            EnterCriticalSection(&cs);//進入臨界區
            //操作數據
            MyMoney*=10;//所有訪問MyMoney變量的程序都需要這樣寫Enter.. Leave...
            LeaveCriticalSection(&cs);//離開臨界區
            DeleteCriticalSection(&cs);//刪除臨界區

            實際遇到的問題:如多線程加載紋理過程中遇到的問題
            step1.創建全局互斥變量,并初始化 
                
            static CRITICAL_SECTION gs_TextureLoadingCS;            //全局互斥變量
                static std::vector<CHRTextureLoadingReq> gs_TextureLoadingReqs;        //全局紋理容器命令
                
                CHRTextureMgrInstance::CHRTextureMgrInstance()
                
            {
                    InitializeCriticalSection( 
            &gs_TextureLoadingCS );
                }


                CHRTextureMgrInstance::
            ~CHRTextureMgrInstance()
                
            {
                    DeleteCriticalSection( 
            &gs_TextureLoadingCS );
                }


            step2.開啟加載紋理多線程
            BOOL CHRTextureMgrInstance::StartTextureLoadingThread()
            {
                gs_bTextureMgrWillDestroy 
            = FALSE;
                gs_bTextureLoadingThreadTerminated 
            = FALSE;
                
            //InitializeCriticalSection( &gs_TextureLoadingCS );
                _beginthread( TextureLoadingThread, NULL, GetHREngine()->GetRenderer()->GetRealDevice() );  //開啟加載紋理線程
                return TRUE;
            }


            void TextureLoadingThread(void* p)
            {
            //    LPDIRECT3DDEVICE8 pD3DDevice = (LPDIRECT3DDEVICE8)p;
                IHRRenderer* RI = GetHREngine()->GetRenderer();
                
            // 當主線程要結束了
                while!gs_bTextureMgrWillDestroy )
                
            {
                    CHRTextureLoadingReq req;
                    BOOL bHasReq 
            = FALSE;
                    EnterCriticalSection( 
            &gs_TextureLoadingCS );                            //進入臨界區
                    if( gs_TextureLoadingReqs.size() > 0 )                                    //操作,取出一個紋理加載
                    {
                        bHasReq 
            = TRUE;
                        req 
            = gs_TextureLoadingReqs[0];
                        gs_TextureLoadingReqs.erase( gs_TextureLoadingReqs.begin() );
                    }

                    LeaveCriticalSection( 
            &gs_TextureLoadingCS );                            //離開臨界區 
                    if( bHasReq )
                    
            {
                        
            if( CreateTextureFromReq( RI, &req ) )
                        
            {
                            PostTextureLoadingAck( req );
                        }

                    }

                    Sleep( 
            1 );
                }

                
            // 這個線程結束了
                gs_bTextureLoadingThreadTerminated = TRUE;
            }


            step2.讀取圖片并壓入容器,邊壓入,邊讀取

                g_nGlobalTextures[eFootprint]    
            = pMgr->RegisterTexture( "Data\\Textures\\Effect\\Footprint.tga", TRUE, 0, TRUE );
                g_nGlobalTextures[eSmoke]        
            = pMgr->RegisterTexture( "Data\\Textures\\Effect\\Smoke.tga", TRUE, 0, TRUE );
                g_nGlobalTextures[eShadow]        
            = pMgr->RegisterTexture( "Data\\Textures\\Effect\\Shadow.tga", TRUE, 0, TRUE );
                g_nGlobalTextures[eHitFlash]    
            = pMgr->RegisterTexture( "Data\\Textures\\Effect\\HitFlash.tga", TRUE, 0, TRUE );
                g_nGlobalTextures[eElectric]    
            = pMgr->RegisterTexture( "Data\\Textures\\Effect\\LightingRed.tga", TRUE, 0, TRUE );
                
                BOOL PostTextureLoadingReq( CHRTextureLoadingReq
            & req )
                
            {
                    EnterCriticalSection( 
            &gs_TextureLoadingCS );
                    gs_TextureLoadingReqs.push_back( req );
                    LeaveCriticalSection( 
            &gs_TextureLoadingCS );
                    
            return TRUE;
                }




            舉個簡單的例子:
            #include "stdafx.h"
            #include 
            <Windows.h>
            #include 
            <iostream>
            #include 
            <process.h>
            using std::cout;
            using std::endl;


            CRITICAL_SECTION cs;
            UINT n_AddValue  
            = 0;

            // first thread
            void FirstThread( LPVOID lParam )
            {
                
            forint i = 0; i < 100; i++ ){
                    EnterCriticalSection( 
            &cs );
                    n_AddValue
            ++;
                    cout 
            << "n_AddValue in FirstThread is "<<n_AddValue <<endl;
                    LeaveCriticalSection( 
            &cs );
                }

            }


            // second thread
            void  SecondThread( LPVOID lParam )
            {
                
            forint i = 0; i < 100; i++ ){
                    EnterCriticalSection( 
            &cs );    
                    n_AddValue
            ++;
                    cout 
            << "n_AddValue in SecondThread is "<<n_AddValue <<endl;
                    LeaveCriticalSection( 
            &cs );
                }


            }



            void main()
            {
                InitializeCriticalSection( 
            &cs );
                
                HANDLE hThread[
            2];
                hThread[
            0= (HANDLE)_beginthread( FirstThread, 0, LPVOID(NULL) );
                hThread[
            1= (HANDLE)_beginthread( SecondThread, 0, LPVOID(NULL) );
                
                
            // 等待線程返回
                WaitForMultipleObjects( 2, hThread, true, INFINITE );

                DeleteCriticalSection( 
            &cs );
                system(
            "pause");
            }


            ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
            臨界區的理解:

            理解EnterCriticalSection 臨界區

             

             

            比如說我們定義了一個共享資源dwTime[100],兩個線程ThreadFuncA和ThreadFuncB都對它進行讀寫操作。當我們想要保證 dwTime[100]的操作完整性,即不希望寫到一半的數據被另一個線程讀取,那么用CRITICAL_SECTION來進行線程同步如下:

            第一個線程函數:

            DWORD   WINAPI   ThreadFuncA(LPVOID   lp)
            {
            EnterCriticalSection(&cs);
            ...
            //   操作dwTime
            ...
            LeaveCriticalSection(&cs);
            return   0;
            }

            寫出這個函數之后,很多初學者都會錯誤地以為,此時cs對dwTime進行了鎖定操作,dwTime處于cs的保護之中。一個“自然而然”的想法就是——cs和dwTime一一對應上了。

            這么想,就大錯特錯了。dwTime并沒有和任何東西對應,它仍然是任何其它線程都可以訪問的。如果你像如下的方式來寫第二個線程,那么就會有問題:

            DWORD   WINAPI   ThreadFuncB(LPVOID   lp)
            {
            ...
            //   操作dwTime
            ...
            return   0;
            }

            當線程ThreadFuncA執行了EnterCriticalSection(&cs),并開始操作dwTime[100]的時候,線程 ThreadFuncB可能隨時醒過來,也開始操作dwTime[100],這樣,dwTime[100]中的數據就被破壞了。

            為了讓CRITICAL_SECTION發揮作用,我們必須在訪問dwTime的任何一個地方都加上 EnterCriticalSection(&cs)和LeaveCriticalSection(&cs)語句。所以,必須按照下面的方式來寫第二個線程函數:

            DWORD   WINAPI   ThreadFuncB(LPVOID   lp)
            {
            EnterCriticalSection(&cs);
            ...
            //   操作dwTime
            ...
            LeaveCriticalSection(&cs);
            return   0;
            }

            這樣,當線程ThreadFuncB醒過來時,它遇到的第一個語句是EnterCriticalSection(&cs),這個語句將對cs變量進行訪問。如果這個時候第一個線程仍然在操作dwTime[100],cs變量中包含的值將告訴第二個線程,已有其它線程占用了cs。因此,第二個線程的 EnterCriticalSection(&cs)語句將不會返回,而處于掛起等待狀態。直到第一個線程執行了 LeaveCriticalSection(&cs),第二個線程的EnterCriticalSection(&cs)語句才會返回,并且繼續執行下面的操作。

            這個過程實際上是通過限制有且只有一個函數進入CriticalSection變量來實現代碼段同步的。簡單地說,對于同一個 CRITICAL_SECTION,當一個線程執行了EnterCriticalSection而沒有執行LeaveCriticalSection的時候,其它任何一個線程都無法完全執行EnterCriticalSection而不得不處于等待狀態

            再次強調一次,沒有任何資源被“鎖定”,CRITICAL_SECTION這個東東不是針對于資源的,而是針對于不同線程間的代碼段的!我們能夠用它來進行所謂資源的“鎖定”,其實是因為我們在任何訪問共享資源的地方都加入了EnterCriticalSection和 LeaveCriticalSection語句,使得同一時間只能夠有一個線程的代碼段訪問到該共享資源而已(其它想訪問該資源的代碼段不得不等待)。

            這就是使用一個CRITICAL_SECTION時的情況。你應該要知道,它并沒有什么可以同步的資源的“集合”。這個概念不正確。

            如果是兩個CRITICAL_SECTION,就以此類推。

             

            雖然臨界區同步速度很快,但卻能用來同步本進程內的線程,而不可用來同步多個進程中的線程

                MFC提供了很多功能完備的類,我用MFC實現了臨界區。MFC為臨界區提供有一個CCriticalSection類,使用該類進行線程同步處理是非常簡單的。只需在線程函數中用CCriticalSection類成員函數Lock()和UnLock()標定出被保護代碼片段即可。Lock()后代碼用到的資源自動被視為臨界區內的資源被保護。UnLock后別的線程才能訪問這些資源。

            posted on 2010-07-08 10:39 風輕云淡 閱讀(1833) 評論(0)  編輯 收藏 引用 所屬分類: C++
            无码超乳爆乳中文字幕久久| 久久免费视频1| 少妇高潮惨叫久久久久久| 亚洲AV无码久久精品狠狠爱浪潮| 久久精品国产99久久久古代| 久久精品国内一区二区三区| 久久激情亚洲精品无码?V| 久久综合伊人77777麻豆| 久久亚洲中文字幕精品有坂深雪 | 香蕉久久夜色精品国产尤物| 亚洲中文久久精品无码| 大香网伊人久久综合网2020| 亚洲精品午夜国产VA久久成人| 久久久九九有精品国产| 一本大道久久香蕉成人网| 97热久久免费频精品99| 麻豆精品久久久久久久99蜜桃| 精品一区二区久久| 77777亚洲午夜久久多喷| 久久久91精品国产一区二区三区 | 人人狠狠综合久久亚洲88| 99精品久久久久久久婷婷| 色婷婷噜噜久久国产精品12p| 精品久久久久久久无码| 久久久久久久久久久精品尤物| 精品国产综合区久久久久久| av无码久久久久不卡免费网站| 亚洲国产婷婷香蕉久久久久久| 亚洲嫩草影院久久精品| 国产精品久久久久AV福利动漫 | 欧美日韩成人精品久久久免费看| 日韩人妻无码精品久久久不卡| 超级碰碰碰碰97久久久久| 久久久久久久亚洲精品| 国产一区二区精品久久凹凸 | 久久精品国产精品亜洲毛片| 亚洲乱码精品久久久久..| 久久久久久久波多野结衣高潮| 免费无码国产欧美久久18| 久久国产精品免费一区| 狠狠久久综合|