现在的位置: 首页 > 综合 > 正文

临界区实现线程同步互斥

2013年09月22日 ⁄ 综合 ⁄ 共 3429字 ⁄ 字号 评论关闭

除了临界区对象进能够被用于一个进程内的线程使用外,临界区对象同于其他互斥体对象一样,也可以提供同步机制.事件,互斥体和信号量对象也能够被用于单个进程实现资源互斥访问,与此相比,为了实现同步互斥访问共享资源,临界区对象提供一种更加轻巧,快速和有效的机制.象互斥体对象一样,临界区对象也可以被一个使用它来阻止同步访问共享资源的线程所用于.例如:一个进程随时可以使用一个临界区对象来阻止其他线程修改一个局数据结构.
进程负责为一个临界区分配内存.典型地,就是宣布一个CRITICAL_SECTION类型的变量.线程在使用它之前,临界区对象必须使用InitializeCriticalSection函数进行初始化.线程使用EnterCriticalSection或TryEnterCriticalSection函数获取临界区所有权,并通过LeaveCriticalSection函数释放临界区所用权.如果当前临界区对象被其他线程所拥有,EnterCriticalSection将无限等待为了临界区所有权.相比之下,一个互斥体对象为了互斥,等待函数会有一个指定的时间段.TryEnterCriticalSection函数无阻塞正在调用的线程而进入临界区.
一旦线程拥有临界区,它必须额外的调用EnterCriticalSection或无阻塞他的执行的TryEnterCriticalSection函数.这样以来,当等待一个已存在的临界区的拥有权时,就不会出现死锁自己.每当它进入临界区时,就必须调用LeaveCriticalSection来释放对临界区的拥有权.
当临界区被初始化之后,进程内的任一个线程都可以调用DeleteCriticalSection函数来释放被分配了的系统资源.DeleteCriticalSection函数被调用之后,这个临界区对象就不能够再被拥有为了同步机制了.
一旦一个临界区对象被特有化之后,通过调用EnterCriticalSection函数而关联度其它的线程将等待为了它的拥有权.没有等到拥有权的线程释

放去继续运行.
SECTICAL_SECTION结构:
typedef struct _RTL_CRITICAL_SECTION {
    PRTL_CRITICAL_SECTION_DEBUG DebugInfo;
    //
    //  The following three fields control entering and exiting the critical
    //  section for the resource
    //
    LONG LockCount;
    LONG RecursionCount;
    HANDLE OwningThread;        // from the thread's ClientId->UniqueThread
    HANDLE LockSemaphore;
    ULONG_PTR SpinCount;        // force size on 64-bit systems when packed
} RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;
typedef RTL_CRITICAL_SECTION CRITICAL_SECTION;
typedef PRTL_CRITICAL_SECTION PCRITICAL_SECTION;
typedef PRTL_CRITICAL_SECTION LPCRITICAL_SECTION;

操作临界区的相关函数
(1)  InitializeCriticalSection
   初始化一个临界区对象,而临界区对象(数据成员)由系统自动维护.
   VOID InitializeCriticalSection(
       LPCRITICAL_SECTION lpCriticalSection //pointer to critical section object
   );
(2) DeleteCriticalSection
    释放一个没有被占有的临界区对象的所有资源.
    VOID DeleteCriticalSection(
        LPCRITICAL_SECTION lpCriticalSection //pointer to critical section object    
    );
(3)  EnterCriticalSection
   用来等待临界区对象的所有权,当调用线程赋予所有权,本函数返回,如果没能等待到,那么导致线程暂停.
    VOID EnterCriticalSection(
       LPCRITICAL_SECTION lpCriticalSection //pointer to critical section object
    );
(4)  LeaveCriticalSection
   释放指定临界区对象所有权
   void LeaveCriticalSection(
       LPCRITICAL_SECTION lpCriticalSection //pointer to critical section object
   );
例子:
CRITICAL_SECTION g_cs; //临界区对象
void main()
{
   HANDLE thread1 = CreateThread(NULL, 0, Fun1Proc, NULL, 0, NULL);
   HANDLE thread2 = CreateThread(NULL, 0, Fun2Proc, NULL, 0, NULL);
   CloseHandle(thread1);
   CloseHandle(thread2);
   //初始化一个临界区对象
   InitializeCriticalSection(&g_cs);
   Sleep(4000);
   //释放一个没有被占有的临界区对象的所有资源
   DeleteCriticalSection(&g_cs);

}

DWORD WINAPI Fun1Proc(LPVOID lpParam)
{
   while(TRUE)
   {
       EnterCriticalSection(&g_cs);
       if (ticket>0)
       {
          cout<<"thread1 sells: "<<ticket--<<endl;
          Sleep(1);
       }
       else
          break;
       LeaveCriticalSection(&g_cs);
   }
   return 0;
}

DWORD WINAPI Fun1Proc(LPVOID lpParam)
{
   while(TRUE)
   {
       EnterCriticalSection(&g_cs);
       if (ticket>0)
       {
          cout<<"thread2 sells: "<<ticket--<<endl;
          Sleep(1);
       }
       else
          break;
       LeaveCriticalSection(&g_cs);
   }
   return 0;
}

//以下是我自己编写实现临界区的类:
//头文件 CriticalSection.h
#pragma once
class CCriticalSection
{
private:
       CRITICAL_SECTION m_CS;
public:
       CCriticalSection()
       {
           ::InitializeCriticalSection(&m_CS);
       }
       ~CCriticalSection()
       {
           ::DeleteCriticalSection(&m_CS);
       }
       operator LPCRITICAL_SECTION()
       {
           return &m_CS;
       }
       void Lock()
       {
           ::EnterCriticalSection(&m_CS);
       }
       void UnLock()
       {
           ::LeaveCriticalSection(&m_CS);
       }
}; 

抱歉!评论已关闭.