クリティカルセクションとは、スレッドの同期を行う為に使用します。 EnterCriticalSection()関数から、LeaveCriticalSection()関数を呼び出すまでの間は、他のスレッドに割り込まれること無く処理を行うことができます。 他のスレッドは、EnterCriticalSection()関数を呼び出した際に、他のスレッドが既にEnterCriticalSection()関数を呼び出していた場合は、 LeaveCriticalSection()関数が呼び出されるまで処理待ち状態になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | #include <stdio.h> #include <tchar.h> #include <iostream> #include <string> #include <process.h> #include <windows.h> // クリティカルセクション CRITICAL_SECTION g_oCS; // カウンタ int g_nCounter = 0; /* スレッドメイン処理 */ unsigned __stdcall ThreadMain ( void * vpArguments ) { std::wcout << L "スレッド開始 <- ThreadId = " << ::GetCurrentThreadId() << L " )" << std::endl; /* スレッドメイン処理 */ BOOL bRun = TRUE; while ( FALSE != bRun ) { std::wcout << L "クリティカルセクション待ち = " << ::GetCurrentThreadId() << std::endl; /* クリティカルセクション開始 EnterCriticalSectionからLeaveCriticalSectionの間は、 他のスレッドは、EnterCriticalSectionで待たされて、 割り込む事ができません。 */ ::EnterCriticalSection( &g_oCS ); // カウンタ+1 if ( 10 > g_nCounter ) { g_nCounter++; std::wcout << L "カウンターを加算( " << g_nCounter << L " ) <- ThreadId = " << ::GetCurrentThreadId() << std::endl; } else { bRun = FALSE; } ::Sleep( 1000 ); // クリティカルセクション終了 ::LeaveCriticalSection( &g_oCS ); } /* スレッドの終了 この値はGetExitCodeThread()で取得できる */ std::wcout << L "スレッド終了 <- ThreadId = " << ::GetCurrentThreadId() << std::endl; ::_endthreadex( 1234 ); // 処理結果 return ( 0 ); } /* スレッドの同期(クリティカルセクション) */ int _tmain ( int argc , _TCHAR* argv[] ) { /* std::wcoutのロケールを設定 これを設定するだけで、std::wcoutで日本語が表示される ようになります。 */ std::wcout.imbue( std::locale( "" , std::locale::ctype ) ); // クリティカルセクションの初期化 ::InitializeCriticalSection( &g_oCS ); // スレッドハンドル HANDLE haThreads[] = { NULL , NULL , NULL }; // スレッドId UINT naThreadIds[] = { 0 , 0 , 0 }; // スレッドの生成 for ( UINT nI = 0; nI < _countof( haThreads ); nI++ ) { // スレッド起動 haThreads[ nI ] = ( HANDLE )::_beginthreadex( NULL // SECURITY_ATTRIBUTES構造体 , 0 // スタックサイズ( 0は呼び出し側と同じサイズ ) , &ThreadMain // スレッド関数 , ( void *)12345678 // スレッド関数への引数 , 0 // 作成オプション( 0 / CREATE_SUSPENDED ) , &naThreadIds[ nI ] // スレッドId ); std::wcout << L "スレッド起動 Id = " << naThreadIds[ nI ] << std::endl; } // スレッドの終了待ち ::WaitForMultipleObjects( _countof( haThreads ), haThreads, TRUE, INFINITE ); // スレッドハンドルの解放 for ( UINT nI = 0; nI < _countof( haThreads ); nI++ ) { ::CloseHandle( haThreads[ nI ] ); } // クリティカルセクションの破棄 ::DeleteCriticalSection( &g_oCS ); // 処理結果 return ( 0 ); } |
スレッド起動 Id = 23268 スレッド開始 <- ThreadId = 23268 ) スレッド起動 Id = 22960 スレッド起動 Id = 21816 スレッド開始 <- ThreadId = 22960 ) クリティカルセクション待ち = 23268 スレッド開始 <- ThreadId = 21816 ) クリティカルセクション待ち = 22960 カウンターを加算( 1クリティカルセクション待ち = 21816 ) <- ThreadId = 23268 クリティカルセクション待ち = 23268 カウンターを加算( 2 ) <- ThreadId = 22960 クリティカルセクション待ち = 22960 カウンターを加算( 3 ) <- ThreadId = 21816 クリティカルセクション待ち = 21816 カウンターを加算( 4 ) <- ThreadId = 23268 クリティカルセクション待ち = 23268 カウンターを加算( 5 ) <- ThreadId = 22960 クリティカルセクション待ち = 22960 カウンターを加算( 6 ) <- ThreadId = 21816 クリティカルセクション待ち = 21816 カウンターを加算( 7 ) <- ThreadId = 23268 クリティカルセクション待ち = 23268 カウンターを加算( 8 ) <- ThreadId = 22960 クリティカルセクション待ち = 22960 カウンターを加算( 9 ) <- ThreadId = 21816 クリティカルセクション待ち = 21816 カウンターを加算( 10 ) <- ThreadId = 23268 クリティカルセクション待ち = 23268 スレッド終了 <- ThreadId = 22960 スレッド終了 <- ThreadId = 21816 スレッド終了 <- ThreadId = 23268