zoukankan      html  css  js  c++  java
  • 线程同步——用户模式下线程同步——关键段实现线程同步

     1  //2.使用关键段实现线程同步
     2  使用时必须有以下几个步骤
     3  //(1)必须先定义 CRITICAL_SECTION 结构
     4  CRITICAL_SECTION  g_cs;
     5  //(2)初始化关键段 CRITICAL_SECTION
     6  InitializeCriticalSection(&g_cs);
     7  //(3)在线程中调用
     8  DWORD WINAPI ThreadFunOne(PVOID pvParam) 
     9  {
    10      EnterCriticalSection(&g_cs)  ;
    11 
    12      //共享的资源应该放在EnterCriticalSection和EnterCriticalSection函数之间
    13 
    14      EnterCriticalSection(&g_cs);
    15      return 0;
    16  }
    17  //(4)清理CRITICAL_SECTION结构,必须确保已经没有资源使用此关键段,否则会出现不可预料的结果
    18  DeleteCriticalSection(&g_cs);
    19 //关于
    20 VOID EnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection ) ;
    21 1)如果没有线程正在访问资源,那么EnterCriticalSection立刻更新成员变量,以表示调用线程
    22     已经获准的对资源的访问,并立即返回,这样线程可以继续执行代码(访问资源)。
    23     2)如果成员变量表示调用线程已经获准访问资源,那么EnterCriticalSection更新变量,以表示调用线程被准获访问次数,
    24     并立即返回。这种情况很少,只有当线程调用LeaveCriticalSection 之前连续调用EnterCriticalSection两次及以上才会发生。
    25     3)如果成员变量表示有一个(调用线程之外的其他)线程已经获准访问资源,那么EnterCriticalSection会使用
    26     一组内核对象,把线程切换为等待状态,等待不会浪费CPU时间,这就完美了。
    27     一句话概括就是:调用 EnterCriticalSection 一个线处理资源,其他线程变为等待。
    28 
    29     VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection )
    30     系统会自动更新 CRITICAL_SECTION 的成员变量并将等待的线程,切换为可调度状态。
    31 
    32 
    33     VOID TryEnterCriticalSection(  LPCRITICAL_SECTION lpCriticalSection ) ;
    34 此函数可以代替 EnterCriticalSection 函数,但是:
    35     此函数从来不会让调用线程等待。它可以通过返回值查看,调用线程是否获准访问资源,
    36     如果其它线程正在访问资源,则返回 FALSE ,否则,返回 TRUE 。
    37 
    38 
    39 #include "windows.h"
    40 #include "iostream"
    41 using namespace std;
    42 long g_x = 0 ;
    43 //(1)必须先定义 CRITICAL_SECTION 结构
    44 CRITICAL_SECTION  g_cs;
    45 
    46 //定义线程函数1
    47 DWORD WINAPI ThreadFunOne(PVOID pvParam) ;
    48 
    49 //定义线程函数2
    50 DWORD WINAPI ThreadFunTwo(PVOID pvParam);
    51 
    52 int main()
    53 {
    54 
    55     //(2)初始化关键段 CRITICAL_SECTION
    56     InitializeCriticalSection(&g_cs);
    57 
    58     //创建线程1
    59     HANDLE hThreadOne = CreateThread(NULL,0,ThreadFunOne,0,0,NULL);
    60     CloseHandle(hThreadOne);
    61 
    62     //创建线程2
    63     HANDLE hThreadTwo = CreateThread(NULL,0,ThreadFunTwo,0,0,NULL);
    64     CloseHandle(hThreadTwo);
    65 
    66     //让主线程先挂起,确保其它线程执行完成
    67     Sleep(1000); 
    68     cout<<g_x<<endl;
    69 
    70     //(4)清理CRITICAL_SECTION结构,必须确保已经没有资源使用此关键段,否则会出现不可预料的结果
    71     DeleteCriticalSection(&g_cs);
    72     return 0 ;
    73 }
    74 
    75 DWORD WINAPI ThreadFunOne(PVOID pvParam) 
    76 {
    77     EnterCriticalSection(&g_cs)  ;
    78 
    79     //共享的资源应该放在EnterCriticalSection和EnterCriticalSection函数之间
    80     g_x++;
    81 
    82     EnterCriticalSection(&g_cs);
    83     return 0;
    84 }
    85 
    86 DWORD WINAPI ThreadFunTwo(PVOID pvParam)
    87 {
    88     EnterCriticalSection(&g_cs)  ;
    89 
    90     //共享的资源应该放在EnterCriticalSection和EnterCriticalSection函数之间
    91     g_x++;
    92 
    93     LeaveCriticalSection(&g_cs);
    94     return 0;
    95 }
    96  
  • 相关阅读:
    UOJ388 [UNR #3] 配对树
    洛谷P6151 [集训队作业2019] 青春猪头少年不会梦到兔女郎学姐
    CF908H New Year and Boolean Bridges
    CF704C Black Widow
    CF1338
    CF1361
    CF1110H Modest Substrings
    CF1322
    CF1182F Maximum Sine
    Elastic Stack(ELK)
  • 原文地址:https://www.cnblogs.com/yfyzy/p/3916179.html
Copyright © 2011-2022 走看看