首页 > 技术文章 > Windows多线程中关键段(Critical Section)的应用

cnpirate 2017-08-02 14:50 原文

先看如下代码:(用Visual Studio 2010按照Win32 Console程序创建向导创建)

 1 #include "stdafx.h"
 2 
 3 #include <process.h>
 4 #include <windows.h>
 5 #include <iostream>
 6 
 7 #include <stdio.h>
 8 #include <stdlib.h>
 9 
10 using namespace std;
11 
12 UINT WINAPI ThreadA(void *args);
13 UINT WINAPI ThreadB(void *args);
14 
15 static CRITICAL_SECTION gCS = {0};
16 
17 int _tmain(int argc, _TCHAR* argv[])
18 {
19     DWORD dwWait = 0;
20     
21     InitializeCriticalSection(&gCS);
22     HANDLE threadA_handle = (HANDLE)_beginthreadex(NULL, 0, ThreadA, NULL, CREATE_SUSPENDED, NULL);
23     HANDLE threadB_handle = (HANDLE)_beginthreadex(NULL, 0, ThreadB, NULL, CREATE_SUSPENDED, NULL);
24     
25 
26     if (INVALID_HANDLE_VALUE == threadA_handle)
27     {
28         cout << GetLastError() << endl;
29     }
30 
31     ResumeThread(threadA_handle);
32     ResumeThread(threadB_handle);
33 
34     HANDLE handleArry[2] = {threadA_handle,
35                             threadB_handle};
36     
37     dwWait = WaitForMultipleObjects(2, handleArry, true, 10000);
38     cout << dwWait << " " << GetLastError() << endl;
39 
40     DeleteCriticalSection(&gCS);
41     CloseHandle(threadA_handle);
42     CloseHandle(threadB_handle);    
43 
44     return 0;
45 }
46 
47 UINT WINAPI ThreadA(void *args)
48 {
49     UINT i = 0;
50     EnterCriticalSection(&gCS);
51     for (i=0; i<10; ++i)
52     {
53         cout << "A: " << i << endl;
54     }
55     cout << endl;
56     LeaveCriticalSection(&gCS);
57 
58     return 0;
59 }
60 
61 UINT WINAPI ThreadB(void *args)
62 {
63     UINT j = 0;
64     EnterCriticalSection(&gCS);
65     for (j=0; j<10; ++j)
66     {
67         cout << "B: " << j << endl;
68     }
69     cout << endl;
70     LeaveCriticalSection(&gCS);
71     return 0;
72 }

【总结】:

关键段属于用户态下的线程同步方式,因此比较快;

关键段用于两个互斥的线程,以保证每个线程独占资源,这种应用的场景举例如下:

  1. 线程A用于实时响应用户的请求访问一个资源;
  2. 线程B用于周期性地访问同一个资源;
  3. 为了保证资源不被破坏,可以采用关键段的方式,同一时刻只允许一个线程访问同一个资源;
  4. 采用线程优先级的方式(线程B的优先级低于线程A)无法实现上述要求,因为Windows系统采用抢占式多线程方式,因此当线程B访问资源时,线程A可以抢占CPU访问同一个资源,那么当线程B可以访问同一个资源时,该资源可能已经被修改了;

【参考】

  1. Windows核心编程(第5版)

推荐阅读