`
蒙面考拉
  • 浏览: 160531 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

对于CRITICAL_SECTION用法的介绍和理解[转]

阅读更多

很多人对CRITICAL_SECTION的理解是错误的,认为CRITICAL_SECTION是锁定了资源,其实,CRITICAL_SECTION是不能够“锁定”资源的,它能够完成的功能,是同步不同线程的代码段。简单说,当一个线程执行了 EnterCritialSection之后,cs里面的信息便被修改了,以指明哪一个线程占用了它。而此时,并没有任何资源被“锁定”。不管什么资源,其它线程都还是可以访问的(当然,执行的结果可能是错误的)。只不过,在这个线程尚未执行LeaveCriticalSection之前,其它线程碰到 EnterCritialSection语句的话,就会处于等待状态,相当于线程被挂起了。 这种情况下,就起到了保护共享资源的作用。
      也正由于CRITICAL_SECTION是这样发挥作用的,所以,必须把每一个线程中访问共享资源的语句都放在EnterCritialSection和LeaveCriticalSection之间。这是初学者很容易忽略的地方。
当然,上面说的都是对于同一个CRITICAL_SECTION而言的。 如果用到两个CRITICAL_SECTION,比如说:
第一个线程已经执行了EnterCriticalSection(&cs)并且还没有执行 LeaveCriticalSection(&cs),这时另一个线程想要执行EnterCriticalSection(&cs2),这种情况是可以的(除非cs2已经被第三个线程抢先占用了)。 这也就是多个CRITICAL_SECTION实现同步的思想。

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

 
  1. DWORD   WINAPI   ThreadFuncA(LPVOID   lp)
  2. {
  3.             EnterCriticalSection(&cs);
  4.             ...
  5.             //   操作dwTime
  6.             ...
  7.             LeaveCriticalSection(&cs);
  8.             return   0;
  9. }


写出这个函数之后,很多初学者都会错误地以为,此时cs对dwTime进行了锁定操作,dwTime处于cs的保护之中。一个“自然而然”的想法就是——cs和dwTime一一对应上了。 这么想,就大错特错了。dwTime并没有和任何东西对应,它仍然是任何其它线程都可以访问的。

如果你像如下的方式来写第二个线程,那么就会有问题:

 
  1. DWORD   WINAPI   ThreadFuncB(LPVOID   lp)
  2. {
  3.             ...
  4.             //   操作dwTime
  5.             ...
  6.             return   0;
  7. }


当线程ThreadFuncA执行了EnterCriticalSection(&cs),并开始操作dwTime[100]的时候,线程ThreadFuncB可能随时醒过来,也开始操作dwTime[100],这样,dwTime[100]中的数据就被破坏了。
      为了让 CRITICAL_SECTION发挥作用,我们必须在访问dwTime的任何一个地方都加上 EnterCriticalSection(&cs)和LeaveCriticalSection(&cs)语句。所以,必须按照下面的方式来写第二个线程函数:

 
  1. DWORD   WINAPI   ThreadFuncB(LPVOID   lp)
  2. {
  3.             EnterCriticalSection(&cs);
  4.             ...
  5.             //   操作dwTime
  6.             ...
  7.             LeaveCriticalSection(&cs);
  8.             return   0;
  9. }


       这样,当线程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这个东东:
第一个线程函数:

 
  1. DWORD   WINAPI   ThreadFuncA(LPVOID   lp)
  2. {
  3.             EnterCriticalSection(&cs);
  4.             for(int   i=0;i <1000;i++)
  5.                         Sleep(1000);
  6.             LeaveCriticalSection(&cs);
  7.             return   0;
  8. }



第二个线程函数:

 
  1. DWORD   WINAPI   ThreadFuncB(LPVOID   lp)
  2. {
  3.             EnterCriticalSection(&cs);
  4.             index=2;
  5.             LeaveCriticalSection(&cs);
  6.             return   0;
  7. }


       这种情况下,第一个线程中间总共Sleep了1000秒钟!它显然没有对任何资源进行什么“有意识”的保护;而第二个线程是要访问资源index的,但是由于第一个线程占用了cs,一直没有Leave,而导致第二个线程不得不登上1000秒钟……
第二个线程,真是可怜哪。。。
这个应该很说明问题了,你会看到第二个线程在1000秒钟之后开始执行index=2这个语句。
也就是说,CRITICAL_SECTION其实并不理会你关心的具体共享资源,它只按照自己的规律办事~

分享到:
评论

相关推荐

    criticalsection.rar_CriticalSection_critical

    通过理解和运用CriticalSection,我们可以有效地解决多线程环境下的数据同步问题,保证程序的正确性和高效性。在实际开发中,结合具体需求,灵活选择适合的同步机制,是实现高质量多线程软件的关键。

    CriticalSection.rar_CriticalSection

    临界区(CriticalSection)是Windows操作系统中用于多线程编程的一种同步机制,它允许一个时间段内只有一线程访问特定的资源或代码段,从而防止数据竞争和其他并发问题。在微软的面试中,理解并能熟练运用临界区API...

    CriticalSection.rar_CCriticalSection_CriticalSection

    本文将深入探讨`CCriticalSection`的工作原理及其在实际应用中的使用方法。 首先,我们来看`CCriticalSection`的基本概念。`CCriticalSection`是一种临界区机制,它允许线程在进入临界区时进行锁定,防止其他线程...

    CriticalSection.rar_CriticalSection_线程临界区

    这个"CriticalSection"示例程序为我们提供了一个实用的教程,帮助理解线程临界区如何在实际编程中应用。通过分析并运行这个程序,我们可以更深入地了解临界区的工作原理,以及如何在多线程环境下正确地保护共享资源...

    critical-section.gz_critical_临界区_线程临界区

    在文档《critical section.doc》中,可能详细讲解了这些原理,并给出了具体的代码示例,帮助开发者更好地理解和应用线程临界区。通过学习这部分内容,开发者可以编写出更加健壮、高效的并发程序,避免因并发问题引发...

    Examples_critical_region.rar_critical_临界区_线程临界区

    在Windows操作系统中,线程临界区(Thread Critical Section)是实现临界区的一种方法。线程临界区提供了线程级别的互斥,确保了在同一时刻只有一个线程能够进入临界区,其他试图进入的线程会被挂起,直到该线程离开...

    WINDOWS读写锁实现

    总之,实现Windows下的读写锁涉及到对`CRITICAL_SECTION`的理解、CPU的`LOCK`指令的运用,以及C++封装技巧。通过这样的设计,我们可以为应用程序提供更高效的并发访问,尤其是在读操作频繁的情况下。在实际应用中,...

    Critical Section

    在Windows操作系统中,临界区域(Critical Section)是一种同步机制,用于保护共享资源免受并发访问带来的冲突。这个概念在Windows 95时代就已经存在,并且对于多线程编程至关重要。临界区域允许一个时间点只有一个...

    临界区(Critical Section)的封装和使用示例

    临界区(Critical Section)是多线程编程中一个重要的概念,它用于保护共享资源免受并发访问的影响,...通过学习和实践这些示例,开发者可以更好地理解和掌握如何在多线程环境中有效地保护共享资源,确保程序的正确性。

    pthread和win32的临界区 Critical Section 比较

    临界区(Critical Section)是线程同步的一种基本方法,它在不同的操作系统和编程库中有不同的实现。本文将深入探讨pthread和Win32 API中的临界区实现,并进行比较。 首先,让我们了解临界区的基本概念。临界区是指...

    操作系统实验临界区的互斥访问

    在WriteW和WriteD线程函数中,使用Lock()和Unlock()方法确保在写入编辑框时的互斥访问。例如,在WriteW线程函数中,线程尝试写入字符'W'到IDC_W编辑框,首先调用`critical_section.Lock()`,然后更新编辑框内容,...

    多线程编程之四——线程的同步

    在`WriteW`和`WriteD`函数中,每个线程在尝试修改编辑框之前都会调用`Lock()`方法来锁定`critical_section`。一旦锁定成功,线程就可以安全地修改编辑框中的内容而不用担心其他线程的干扰。修改完成后,线程会调用`...

    Critical_test.rar_进程与线程_Visual_C++_

    在Visual C++中,可以使用CRITICAL_SECTION结构体和相关API(如InitializeCriticalSection、EnterCriticalSection、LeaveCriticalSection和DeleteCriticalSection)来管理临界区,确保线程安全。 五、线程同步与...

    多线程编程四

    在具体实例中,我们通过一个简单的例子来演示`CCriticalSection`的使用方法: 1. **声明和初始化**:首先声明一个`CCriticalSection`对象`critical_section`。 2. **锁定临界区**:在需要访问共享资源之前,调用`...

    Critical(VC2010条件下通过临界区实现多线程同步)

    在VC2010中,我们可以使用Windows API的`CRITICAL_SECTION`结构和相关的API函数来实现临界区。以下是一个简单的示例,展示如何定义和使用临界区: 1. 定义临界区对象: ```cpp CRITICAL_SECTION cs; ...

    如何使用CSingleLock类

    CSingleLock类是MFC(Microsoft Foundation Classes)库中用于多线程同步的一个关键组件,主要用来实现线程之间的互斥访问,确保同一时间...理解和正确使用CSingleLock能帮助我们构建更加健壮和安全的多线程应用程序。

    C++(C)多线程编程之四.pdf

    综上所述,文件中涉及的C++多线程编程知识点包含了对同步机制的深入理解和应用,包括但不限于临界区、事件、互斥锁和信号量的使用,以及多线程的创建、管理和线程间的通信。掌握这些知识点对于开发出高效、安全的多...

    CriticalSeciton实现线程同步

    本文将详细探讨`CriticalSection`的原理、使用方法及其在VC++中的应用。 一、`CriticalSection`介绍 `CriticalSection`是Windows操作系统提供的一种内核对象,它提供了互斥访问共享资源的功能。与Mutex相比,`...

    afxbeginthread的理解

    在代码中,我们可以使用 CRITICAL_SECTION 来保护共享资源,并使用 EnterCriticalSection 和 LeaveCriticalSection 来控制线程的同步。同时,我们也可以使用 m_bAutoDelete 变量来控制线程的自动释放。 下面是一份...

Global site tag (gtag.js) - Google Analytics