わびさびサンプルソース

WindowsやHTML5などのプログラムのサンプルコードやフリーソフトを提供します。

スレッドの同期(クリティカルセクション)

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






わびさびサンプルソース

WindowsやHTML5などのプログラムのサンプルコードやフリーソフトを提供します。