zoukankan      html  css  js  c++  java
  • 理解EnterCriticalSection 临界区

    通俗解释就像上厕所: 
    门锁了,就等着,等到别人出来了,进去锁上,然后该干什么干什么,干完了,把门打开

    门没锁,就进去,锁上,然后该干什么干什么,干完了,把门打开

    -------------------------------------------------- 
    多线程中用来确保同一时刻只有一个线程操作被保护的数据

    InitializeCriticalSection(&cs);//初始化临界区 
    EnterCriticalSection(&cs);//进入临界区 
    //操作数据 
    MyMoney*=10;//所有访问MyMoney变量的程序都需要这样写Enter.. Leave... 
    LeaveCriticalSection(&cs);//离开临界区 
    DeleteCriticalSection(&cs);//删除临界区

    多个线程操作相同的数据时,一般是需要按顺序访问的,否则会引导数据错乱,无法控制数据,变成随机变量。为解决这个问题,就需要引入互斥变量,让每个线程都按顺序地访问变量。这样就需要使用EnterCriticalSection和LeaveCriticalSection函数。

    比如说我们定义了一个共享资源dwTime[100],两个线程ThreadFuncA和ThreadFuncB都对它进行读写操作。当我们想要保证 dwTime[100]的操作完整性,即不希望写到一半的数据被另一个线程读取,那么用CRITICAL_SECTION来进行线程同步如下: 

    第一个线程函数: 

    DWORD   WINAPI   ThreadFuncA(LPVOID   lp) 

    EnterCriticalSection(&cs); 
    ... 
    //   操作dwTime 
    ... 
    LeaveCriticalSection(&cs); 
    return   0; 


    写出这个函数之后,很多初学者都会错误地以为,此时cs对dwTime进行了锁定操作,dwTime处于cs的保护之中。一个“自然而然”的想法就是——cs和dwTime一一对应上了。 

    这么想,就大错特错了。dwTime并没有和任何东西对应,它仍然是任何其它线程都可以访问的。如果你像如下的方式来写第二个线程,那么就会有问题: 

    DWORD   WINAPI   ThreadFuncB(LPVOID   lp) 

    ... 
    //   操作dwTime 
    ... 
    return   0; 


    当线程ThreadFuncA执行了EnterCriticalSection(&cs),并开始操作dwTime[100]的时候,线程 ThreadFuncB可能随时醒过来,也开始操作dwTime[100],这样,dwTime[100]中的数据就被破坏了。 

    为了让CRITICAL_SECTION发挥作用,我们必须在访问dwTime的任何一个地方都加上 EnterCriticalSection(&cs)和LeaveCriticalSection(&cs)语句。所以,必须按照下面的 方式来写第二个线程函数: 

    DWORD   WINAPI   ThreadFuncB(LPVOID   lp) 

    EnterCriticalSection(&cs); 
    ... 
    //   操作dwTime 
    ... 
    LeaveCriticalSection(&cs); 
    return   0; 


    这样,当线程ThreadFuncB醒过来时,它遇到的第一个语句是EnterCriticalSection(&cs),这个语句将对cs变量 进行访问。如果这个时候第一个线程仍然在操作dwTime[100],cs变量中包含的值将告诉第二个线程,已有其它线程占用了cs。因此,第二个线程的 EnterCriticalSection(&cs)语句将不会返回,而处于挂起等待状态。直到第一个线程执行了 LeaveCriticalSection(&cs),第二个线程的EnterCriticalSection(&cs)语句才会返回, 并且继续执行下面的操作。 

    这个过程实际上是通过限制有且只有一个函数进入CriticalSection变量来实现代码段同步的。简单地说,对于同一个 CRITICAL_SECTION,当一个线程执行了EnterCriticalSection而没有执行LeaveCriticalSection的时 候,其它任何一个线程都无法完全执行EnterCriticalSection而不得不处于等待状态。 

    再次强调一次,没有任何资源被“锁定”,CRITICAL_SECTION这个东东不是针对于资源的,而是针对于不同线程间的代码段的!我们能够用它来进 行所谓资源的“锁定”,其实是因为我们在任何访问共享资源的地方都加入了EnterCriticalSection和 LeaveCriticalSection语句,使得同一时间只能够有一个线程的代码段访问到该共享资源而已(其它想访问该资源的代码段不得不等待)。 

    这就是使用一个CRITICAL_SECTION时的情况。你应该要知道,它并没有什么可以同步的资源的“集合”。这个概念不正确。 

    如果是两个CRITICAL_SECTION,就以此类推

  • 相关阅读:
    A1066 Root of AVL Tree (25 分)
    A1099 Build A Binary Search Tree (30 分)
    A1043 Is It a Binary Search Tree (25 分) ——PA, 24/25, 先记录思路
    A1079; A1090; A1004:一般树遍历
    A1053 Path of Equal Weight (30 分)
    A1086 Tree Traversals Again (25 分)
    A1020 Tree Traversals (25 分)
    A1091 Acute Stroke (30 分)
    A1103 Integer Factorization (30 分)
    A1032 Sharing (25 分)
  • 原文地址:https://www.cnblogs.com/zhangzhifeng/p/6000115.html
Copyright © 2011-2022 走看看