クリティカルセクションとは、スレッドの同期を行う為に使用します。 EnterCriticalSection()関数から、LeaveCriticalSection()関数を呼び出すまでの間は、他のスレッドに割り込まれること無く処理を行うことができます。 他のスレッドは、EnterCriticalSection()関数を呼び出した際に、他のスレッドが既にEnterCriticalSection()関数を呼び出していた場合は、 LeaveCriticalSection()関数が呼び出されるまで処理待ち状態になります。
#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