【线程同步】临界区与互斥量

Win32 中关于进程和线程的协调工作是由同步机制来完成的,同步机制相当于线程间的红绿灯。

一. 同步和异步

举个例子:

PostMessage(),是把消息放到对方的消息队列中,然后不管三七二十一,就回到原调用点继续执行,这就是异步。

SendMessage(),就像调用一般性函数,直到调用的函数结束,才会回到原点,这就是同步行为。

二. Critical Sections

如果一个线程已经进入某个临界区,则另一个线程就绝不能够进入同一个临界区。

  

  //初始化一个临界区
    VOID InitializeCriticalSection(
      LPCRITICAL_SECTION lpCriticalSection  // critical section
    );
     
    //消除一个临界区
    VOID DeleteCriticalSection(
      LPCRITICAL_SECTION lpCriticalSection   // critical section
    );
     
    //进入临界区
    VOID EnterCriticalSection(
      LPCRITICAL_SECTION lpCriticalSection  // critical section
    );
     
    //离开临界区
    VOID LeaveCriticalSection(
      LPCRITICAL_SECTION lpCriticalSection   // critical section
    );
     
    例如:
    CRITICAL_SECTION gCriticalSection;
     
    void Function()
    {
        InitializeCriticalSection(&gCriticalSection);
     
        EnterCriticalSection(&gCriticalSection);
     
        //Do something here
     
        LeaveCriticalSection(&gCriticalSection);
     
        DeleteCriticalSection(&gCriticalSection);
    }

一旦线程进入一个临界区,则它就可以一再的重复进入该临界区,当然每个进入操作都必须对应离开操作。

也就是EnterCriticalSection( ),可以嵌套。

但是千万不要在临界区中调用 sleep(),或任何 Wait..() 函数。

临界区的缺点是:没有办法知道进入临界区中的那个线程是生是死。如果那个线程在进入临界区后当掉了,而且没有退出来,那么系统就没有办法消除掉此临界区。

三. Mutexes

Mutexes 用途和 Critical Section 非常类似,线程拥有 mutex 就好象线程进入 critical section 一样,但是它牺牲速度以增加弹性。

一旦没有任何线程拥有那个 mutex,这个 mutex 便处于激发状态

它与临界区的区别是:

1. Mutexes 操作要比 Critical Section 费时的多。

2. Mutexes 可以跨进程使用,Critical Section 则只能在同一进程中使用。

3. 等待一个 Mutex 时,你可以指定"结束等待"的时间长度,而 Critical Section 则不行。

    HANDLE CreateMutex(
      LPSECURITY_ATTRIBUTES lpMutexAttributes,  // 安全属性,默认为NULL
      BOOL bInitialOwner,                       // initial owner
      LPCTSTR lpName                            // mutex 的名称,是一个字符串
    );
    //返回值:如果成功返回 handle,否则返回 NULL
     
    HANDLE OpenMutex(
      DWORD dwDesiredAccess,  // access
      BOOL bInheritHandle,    // inheritance option
      LPCTSTR lpName          // object name
    );
    //打开一个已经存在的 mutex
     
    BOOL ReleaseMutex(
      HANDLE hMutex   // handle to mutex
    );
     
    //调用过程如下:
    CreateMutex(); //创建
    WaitForXXXObject(); //等待
     
    ReleaseMutex(); //释放
    CloseHandle(); //关闭

说明:

1. Mutex 的拥有权:

Mutex 的拥有权并非属于那个产生它的线程,而是那个最后对些 Mutex 进行 WaitXXX() 操作并且尚未进行 ReleaseMutex() 操作的线程。

2. Mutex 被舍弃:

如果线程在结束前没有调用 ReleaseMutex(),比如线程调用了 EXitThread() 或者因为当掉而结束。这时的 mutex 不会被摧毁,而是被视为"未被拥有"以及"未被激发"的状态,在下一个 WaitXXX() 中线程会被以WAIT_ABANDONED_0 (WAIT_ABANDONED_0_n + 1 )来通知。

3. 最初拥有者:

CreateMutex(),第二个参数 bInitialOwner,允许你指定现行线程是否立刻拥有产生出来的 mutex。

如果没有指定立刻拥有的情况:

    HANDLE hMutex = CreateMutex(NULL, FALSE, "Sample Name");
     
    int result = WaitForSingleObject(hMutex, INFINITE);

可能发生,在 CreateMutex 完成之后,发生了 context switch,执行权切换到另一个线程,那么其它进程就有可能在 mutex 的产生者调用 WaitForSingleObject( ) 之前,锁住这个 mutex 对象。


原文:https://blog.csdn.net/lwbeyond/article/details/7617234
 

 

猜你喜欢

转载自blog.csdn.net/bandaoyu/article/details/83998099