• <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++ Programmer's Cookbook

            {C++ 基礎(chǔ)} {C++ 高級(jí)} {C#界面,C++核心算法} {設(shè)計(jì)模式} {C#基礎(chǔ)}

            C++多線程(六)

            多線程之線程同步Mutex (功能與CriticalSection相同,保證某一時(shí)刻只有一個(gè)線程能夠訪問共享資源,但是是內(nèi)核對(duì)象,所以訪問速度要比CriticalSection要慢,但是增加了等待超時(shí)的功能,使用時(shí)可以根據(jù)實(shí)際的情況選擇其一

            一 Mutex
                互斥對(duì)象(mutex)內(nèi)核對(duì)象能夠確保線程擁有對(duì)單個(gè)資源的互斥訪問權(quán)。實(shí)際上互斥對(duì)象是因此而得名的。互斥對(duì)象包含一個(gè)使用數(shù)量,一個(gè)線程ID和一個(gè)遞歸計(jì)數(shù)器。
                互斥對(duì)象的行為特性與關(guān)鍵代碼段相同,但是互斥對(duì)象屬于內(nèi)核對(duì)象,而關(guān)鍵代碼段則屬于用戶方式對(duì)象。這意味著互斥對(duì)象的運(yùn)行速度比關(guān)鍵代碼段要慢。但是這也意味著不同進(jìn)程中的多個(gè)線程能夠訪問單個(gè)互斥對(duì)象,并且這意味著線程在等待訪問資源時(shí)可以設(shè)定一個(gè)超時(shí)值。

                ID用于標(biāo)識(shí)系統(tǒng)中的哪個(gè)線程當(dāng)前擁有互斥對(duì)象,遞歸計(jì)數(shù)器用于指明該線程擁有互斥對(duì)象的次數(shù)。
                互斥對(duì)象有許多用途,屬于最常用的內(nèi)核對(duì)象之一。通常來說,它們用于保護(hù)由多個(gè)線程訪問的內(nèi)存塊。如果多個(gè)線程要同時(shí)訪問內(nèi)存塊,內(nèi)存塊中的數(shù)據(jù)就可能遭到破壞。互斥對(duì)象能夠保證訪問內(nèi)存塊的任何線程擁有對(duì)該內(nèi)存塊的獨(dú)占訪問權(quán),這樣就能夠保證數(shù)據(jù)的完整性。

            互斥對(duì)象的使用規(guī)則如下:

            • 如果線程ID是0(這是個(gè)無效ID),互斥對(duì)象不被任何線程所擁有,并且發(fā)出該互斥對(duì)象的通知信號(hào)。

            • 如果ID是個(gè)非0數(shù)字,那么一個(gè)線程就擁有互斥對(duì)象,并且不發(fā)出該互斥對(duì)象的通知信號(hào)。

            • 與所有其他內(nèi)核對(duì)象不同, 互斥對(duì)象在操作系統(tǒng)中擁有特殊的代碼,允許它們違反正常的規(guī)則。

            若要使用互斥對(duì)象,必須有一個(gè)進(jìn)程首先調(diào)用CreateMutex,以便創(chuàng)建互斥對(duì)象:
            HANDLECreateMutex(
               PSECURITY_ATTRIBUTES psa,
               BOOL fInitialOwner,
               PCTSTR pszName);
             InitialOwner參數(shù)用于控制互斥對(duì)象的初始狀態(tài)。如果傳遞FALSE(這是通常情況下傳遞的值),那么互斥對(duì)象的ID和遞歸計(jì)數(shù)器均被設(shè)置為0。這意味著該互斥對(duì)象沒有被任何線程所擁有,因此要發(fā)出它的通知信號(hào)。
            如果為fInitialOwner參數(shù)傳遞TRUE,那么該對(duì)象的線程ID被設(shè)置為調(diào)用線程的ID,遞歸計(jì)數(shù)器被設(shè)置為1。由于ID是個(gè)非0數(shù)字,因此該互斥對(duì)象開始時(shí)不發(fā)出通知信號(hào)。

            通過調(diào)用一個(gè)等待函數(shù),并傳遞負(fù)責(zé)保護(hù)資源的互斥對(duì)象的句柄,線程就能夠獲得對(duì)共享資源的訪問權(quán)。在內(nèi)部,等待函數(shù)要檢查線程的ID,以了解它是否是0(互斥對(duì)象發(fā)出通知信號(hào))。如果線程ID是0,那么該線程ID被設(shè)置為調(diào)用線程的ID,遞歸計(jì)數(shù)器被設(shè)置為1,同時(shí),調(diào)用線程保持可調(diào)度狀態(tài)。

            如果等待函數(shù)發(fā)現(xiàn)ID不是0(不發(fā)出互斥對(duì)象的通知信號(hào)),那么調(diào)用線程便進(jìn)入等待狀態(tài)。系統(tǒng)將記住這個(gè)情況,并且在互斥對(duì)象的ID重新設(shè)置為0時(shí),將線程ID設(shè)置為等待線程的ID,將遞歸計(jì)數(shù)器設(shè)置為1,并且允許等待線程再次成為可調(diào)度線程。與所有情況一樣,對(duì)互斥內(nèi)核對(duì)象進(jìn)行的檢查和修改都是以原子操作方式進(jìn)行的。

            一旦線程成功地等待到一個(gè)互斥對(duì)象,該線程就知道它已經(jīng)擁有對(duì)受保護(hù)資源的獨(dú)占訪問權(quán)。試圖訪問該資源的任何其他線程(通過等待相同的互斥對(duì)象)均被置于等待狀態(tài)中。當(dāng)目前擁有對(duì)資源的訪問權(quán)的線程不再需要它的訪問權(quán)時(shí),它必須調(diào)用ReleaseMutex函數(shù)來釋放該互斥對(duì)象:
            BOOL ReleaseMutex(HANDLE hMutex);
            該函數(shù)將對(duì)象的遞歸計(jì)數(shù)器遞減1。

            當(dāng)該對(duì)象變?yōu)橐淹ㄖ獱顟B(tài)時(shí),系統(tǒng)要查看是否有任何線程正在等待互斥對(duì)象。如果有,系統(tǒng)將“按公平原則”選定等待線程中的一個(gè),為它賦予互斥對(duì)象的所有權(quán)。當(dāng)然,這意味著線程I D被設(shè)置為選定的線程的ID,并且遞歸計(jì)數(shù)器被置為1。如果沒有其他線程正在等待互斥對(duì)象,那么該互斥對(duì)象將保持已通知狀態(tài),這樣,等待互斥對(duì)象的下一個(gè)線程就立即可以得到互斥對(duì)象。

            二 API

            Mutex function Description
            CreateMutex Creates or opens a named or unnamed mutex object.
            CreateMutexEx Creates or opens a named or unnamed mutex object and returns a handle to the object.
            OpenMutex Opens an existing named mutex object.
            ReleaseMutex Releases ownership of the specified mutex object.

            三 實(shí)例
            來自msdn的實(shí)例:在線程函數(shù)中有一個(gè)循環(huán),在每個(gè)循環(huán)的開始都取得Mutex,然后對(duì)全局或靜態(tài)操作,相當(dāng)于在關(guān)鍵代碼段操作,然后在使用完以后釋放它,大家可以執(zhí)行,查看結(jié)果。

            #include <windows.h>
            #include 
            <stdio.h>

            #define THREADCOUNT 64  //less than 64
            HANDLE ghMutex; 
            int g_x = 0;

            DWORD WINAPI WriteToDatabase(LPVOID);

            void main()
            {
                HANDLE aThread[THREADCOUNT];
                DWORD ThreadID;
                
            int i;

                
            // Create a mutex with no initial owner
                ghMutex = CreateMutex( 
                    NULL,              
            // default security attributes
                    FALSE,             // initially not owned
                    NULL);             // unnamed mutex

                
            if (ghMutex == NULL) 
                
            {
                    printf(
            "CreateMutex error: %d\n", GetLastError());
                    
            return;
                }


                
            // Create worker threads

                
            for( i=0; i < THREADCOUNT; i++ )
                
            {
                    aThread[i] 
            = CreateThread( 
                                 NULL,       
            // default security attributes
                                 0,          // default stack size
                                 (LPTHREAD_START_ROUTINE) WriteToDatabase, 
                                 NULL,       
            // no thread function arguments
                                 0,          // default creation flags
                                 &ThreadID); // receive thread identifier

                    
            if( aThread[i] == NULL )
                    
            {
                        printf(
            "CreateThread error: %d\n", GetLastError());
                        
            return;
                    }

                }


                
            // Wait for all threads to terminate

                WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);

                
            // Close thread and mutex handles
                for( i=0; i < THREADCOUNT; i++ )
                    CloseHandle(aThread[i]);
                CloseHandle(ghMutex);

                printf(
            "g_x is :%d\n",g_x);
            }


            DWORD WINAPI WriteToDatabase( LPVOID lpParam )

                DWORD dwCount
            =0, dwWaitResult; 

                
            // Request ownership of mutex.

                
            while( dwCount < 100 )
                

                    dwWaitResult 
            = WaitForSingleObject( 
                        ghMutex,    
            // handle to mutex
                        INFINITE);  // no time-out interval
             
                    
            switch (dwWaitResult) 
                    
            {
                        
            // The thread got ownership of the mutex
                        case WAIT_OBJECT_0: 
                            __try 

                                g_x
            ++;
                                
            // TODO: Write to the database
                                printf("Thread %d writing to database\n"
                                       GetCurrentThreadId());
                                dwCount
            ++;
                            }
             

                            __finally 

                                
            // Release ownership of the mutex object
                                if (! ReleaseMutex(ghMutex)) 
                                

                                    
            // Deal with error.
                                }
             
                            }
             
                            
            break

                        
            // The thread got ownership of an abandoned mutex
                        case WAIT_ABANDONED: 
                            
            return FALSE; 
                    }

                }

                
            return TRUE; 
            }


            四 參考

            posted on 2007-07-29 22:46 夢(mèng)在天涯 閱讀(4127) 評(píng)論(3)  編輯 收藏 引用 所屬分類: CPlusPlus

            評(píng)論

            # re: C++多線程(六) 2007-07-29 23:27 阿福

            C++是沒有__finally這個(gè)關(guān)鍵字的,這是MFC里面提供的關(guān)鍵字嗎?  回復(fù)  更多評(píng)論   

            # re: C++多線程(六) 2007-07-30 09:13 夢(mèng)在天涯

            __try __finally 應(yīng)該是windows SEH在VC下的實(shí)現(xiàn)把。

            C++本身是沒有finally的。  回復(fù)  更多評(píng)論   

            # re: C++多線程(六) 2007-07-30 11:18 pass86

            __try __finally反掌不是標(biāo)準(zhǔn)C++里,可能是WIN32 SDK里的,也可能是MFC中的,了解較少。LZ的系列帖子贊一個(gè)。  回復(fù)  更多評(píng)論   

            公告

            EMail:itech001#126.com

            導(dǎo)航

            統(tǒng)計(jì)

            • 隨筆 - 461
            • 文章 - 4
            • 評(píng)論 - 746
            • 引用 - 0

            常用鏈接

            隨筆分類

            隨筆檔案

            收藏夾

            Blogs

            c#(csharp)

            C++(cpp)

            Enlish

            Forums(bbs)

            My self

            Often go

            Useful Webs

            Xml/Uml/html

            搜索

            •  

            積分與排名

            • 積分 - 1804434
            • 排名 - 5

            最新評(píng)論

            閱讀排行榜

            久久青青草原精品国产软件| 伊人久久五月天| 色综合久久久久综合体桃花网 | 国产精品久久久久影视不卡| 狠狠色丁香久久婷婷综合_中| 精品国际久久久久999波多野| 亚洲中文字幕久久精品无码APP | 亚洲色欲久久久综合网| 亚洲国产精品狼友中文久久久| 久久久久亚洲av毛片大| 99久久久久| 久久国产精品波多野结衣AV| 国产精品亚洲综合专区片高清久久久| 久久91精品国产91久久户| 色综合久久88色综合天天| 国产农村妇女毛片精品久久| 国产成人99久久亚洲综合精品| 国内精品久久久久久久影视麻豆 | 伊人久久无码精品中文字幕| 中文字幕精品无码久久久久久3D日动漫| 日韩AV毛片精品久久久| 亚洲国产成人乱码精品女人久久久不卡 | www久久久天天com| 久久99精品久久久久久| 久久久久久久99精品免费观看| 中文字幕亚洲综合久久2| 久久婷婷五月综合97色直播| 亚洲国产高清精品线久久| 久久久久国产精品嫩草影院| 久久国产精品一国产精品金尊| 99久久精品毛片免费播放| 久久99精品国产99久久6| 伊人久久大香线蕉AV一区二区| 一本一本久久a久久综合精品蜜桃| 久久精品国产亚洲77777| 91久久精品电影| 18禁黄久久久AAA片| 91精品国产91久久久久久| 亚洲国产一成久久精品国产成人综合 | 久久九九兔免费精品6| 国产精品久久久久久久|