クリティカルセクションとは、スレッドの同期を行う為に使用します。 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