• Windows多线程中关键段(Critical Section)的应用


    先看如下代码:(用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版)
  • 相关阅读:
    《编写高质量代码》读书笔记
    IL,Emit之OpCodes说明(备查)
    每天进步一点点
    DOCTYPE 与浏览器模式分析[转]
    一个EL IF表达式引发的血案
    JVM系列文章
    SunOs设置环境变量
    Solaris系统查看进程与端口对应关系的命令
    jsp 报错调试
    vi命令提示:Terminal too wide
  • 原文地址:https://www.cnblogs.com/cnpirate/p/7273850.html
Copyright © 2020-2023  润新知