线程同步的方式主要有:临界区、互斥区、事件、信号量四种方式。
前边讲过了互斥器线程同步-----windows核心编程-互斥器(Mutexes),这章我来介绍一下信号量(semaphore)线程同步。
理论上说,mutex是semaphore的一种退化。如果你产生一个semaphore并令最大值为1,那就是一个mutex。也因此,mutex又常被称为binary semaphore。如果某个线程拥有一个binary semaphore,那么就没有其他线程能够获得其拥有权。但是在win32中,这两种东西的拥有权的意义完全不同,所以它们不能够交换使用,semaphore不像mutex,它并没有所谓的“wait abandoned”状态可以被其他线程侦测到。
每当一个锁定动作成功,semaphore的现值就会减1,你可以使用任何一种wait...()函数来要求锁定一个semaphore。如果semaphore的现值不为0,wait...()函数会立刻返回,这和mutex很像,当没有任何线程拥有mutex,wait...()函数会立刻返回。
注意,如果锁定成功,你也不会收到semaphore的拥有权。因为可以有一个以上的线程同时锁定一个semaphore。所以谈semaphore的拥有权并没有太多实际意义。在semaphore身上并没有所谓“独占锁定”这种事情。也因为没有所有权的观念,一个线程可以反复调用wait...()函数以产生新的锁定。这和mutex绝不相同:拥有mutex的线程不论再调用多少次wait...()函数,也不会被阻塞住。
与mutex不同的是,调用ReleaseSemaphore()的那个线程,并不一定就得是调用wait...()的那个线程。
任何线程都可以在任何时间调用ReleaseSemaphore(),解除被任何线程锁定的semaphore。
以下是我对三种同步方式中,常用到的函数的总结。
临界区 | 互斥器 | 信号量 |
CRITICAL_SECTION InitializeCriticalSection() |
CreateMutex() OpenMutex() |
CreateSemaphore |
EnterCriticalSection() | WaitForSingleObject() WaitForMultipleObjects() MsgWaitForMultipleObjects() |
WaitForSingleObject() WaitForMultipleObjects() MsgWaitForMultipleObjects() ... |
LeaveCriticalSection() | ReleaseMutex() | ReleaseSemaphore() |
DeleteCriticalSection() | CloseHandle() | CloseHandle() |
事件线程同步----- window核心编程-内核对象线程同步