什么是Critical Section Objects?

Critical section object提供了与mutex object(互斥对象)相同的同步机制, 不同之处在于critical section只能被一个进程中的线程使用. Event, mutex和semaphore object也能用在单个进程的应用程序中, 但是critical section objects提供了稍微快一点的, 更有效的互斥同步机制. 如同mutex object, 一个critical section object一次尽可以被一个线程拥有, 这使得他对于并发访问时保护共享资源非常有用. 与mutex object不同的是, 没办法说明一个critical section是否已经被遗弃.

进程负责为critical section使用的内存进行分配. 典型地, 这种分配通过简单地声明一个CRITICAL_SECTION类型的变量来实现. 在进程中的线程可以使用它之前, 需要使用InitializeCriticalSection 或者是InitializeCriticalSectionAndSpinCount函数来初始化critical section.

线程使用EnterCriticalSection 或者是TryEnterCriticalSection函数来请求对critical section的所有权. 它使用LeaveCriticalSection函数来释放对critical section的所有权. 如果critical section对象目前正被另一个线程所拥有, EnterCriticalSection 函数会无限地等待所有权的释放. 相对比, 当一个mutex对象被用在互斥访问中的时候, wait functions会接受一个超时的时间限制. TryEnterCriticalSection 函数会试图进入critical section而不会阻塞调用者线程.

当一个线程拥有critical section的时候, 它能够进行额外的对于EnterCriticalSection 或者TryEnterCriticalSection 的调用, 而不会阻塞它的执行. 这样就阻止了线程在等待它已经拥有了的critical section时把自己死锁掉. 要释放掉它的所有权, 线程必须每次进入critical section时都调用一次LeaveCriticalSection. 哪个等待中的线程会先请求critical section的所有权是不一定的, 没有这种保证.

线程使用InitializeCriticalSectionAndSpinCount 或者SetCriticalSectionSpinCount 函数来制定critical section的spin count. Spin的意思是当一个线程试图获取一个已经被锁掉的critical section的所有权时, 线程会进入一个循环, 去检查这个锁是否已经开启, 如果锁没有被释放, 那么线程就会进入休眠状态. 在单个处理器的系统中, spin count会被忽略掉, 并且critical section spin count会被设置为0. 在多处理器系统中, 如果critical section不可用, 那么调用者线程会在执行与critical section相关的旗语上的等待操作前, 循环dwSpinCount 次. 如果critical section 在spin操作的时候被释放了, 那么调用线程就避免了进入等待的操作.

任何线程都可以使用DeleteCriticalSection函数来释放在critical section对象初始化时分配的系统资源. 这个函数调用结束之后, critical section对象就不能再用来进行同步了.

当一个critical section对象被拥有的时候, 受影响的只是那些在EnterCriticalSection调用中的等待所有权的线程. 没有等待critical section的线程可以自由地继续执行.

代码举例

==========

下面的例子展示了一个线程如何初始化, 进入, 和释放一个critical section. 它使用了InitializeCriticalSectionAndSpinCount, EnterCriticalSection, LeaveCriticalSection, 和 DeleteCriticalSection 函数.

   1:  // Global variable
   2:  CRITICAL_SECTION CriticalSection; 
   3:   
   4:  void main()
   5:  {
   6:      ...
   7:   
   8:      // Initialize the critical section one time only.
   9:      if (!InitializeCriticalSectionAndSpinCount(&CriticalSection, 
  10:          0x80000400) ) 
  11:          return;
  12:      ...
  13:   
  14:      // Release resources used by the critical section object.
  15:      DeleteCriticalSection(&CriticalSection)
  16:  }
  17:   
  18:  DWORD WINAPI ThreadProc( LPVOID lpParameter )
  19:  {
  20:      ...
  21:   
  22:      // Request ownership of the critical section.
  23:      EnterCriticalSection(&CriticalSection); 
  24:   
  25:      // Access the shared resource.
  26:   
  27:      // Release ownership of the critical section.
  28:      LeaveCriticalSection(&CriticalSection);
  29:   
  30:      ...
  31:  }

原文:http://msdn.microsoft.com/en-us/library/ms682530(VS.85).aspx

http://msdn.microsoft.com/en-us/library/ms686908(VS.85).aspx

原文地址:https://www.cnblogs.com/awpatp/p/1620100.html