多线程同步方法:临界区、事件、信号量、互斥对象

一、临界区(Critical Section)

临界区是指一段独占某些共享资源的访问代码。任意时刻只容许一个线程对共享资源进行访问,如果有多个线程同时访问,那么在一个线程进入临界区后,其他线程只得等待直到该线程离开临界区。
注意:
一个线程进入临界区,其他试图进入该临界区的线程就会被挂起,不要在临界区执行长时间操作;
临界区只能用于同步本进程内的线程;
进入与离开临界区需同时匹配,如果不出临界区会导致其他线程一直等待。

CRITICAL_SECTION  cs; 声明临界区对象
EnterCriticalSection(&cs); 进入临界区
do something...
LeaveCriticalSection(&cs); 离开临界区

二、事件内核对象

事件内核对象通过通知操作的方式保持线程同步。WaitForSingleObject函数只会在事件被置位SetEvent后才返回,继续执行被保护代码,然后事件自动复位(初始状态)。
注意:
事件内核对象能够跨进程同步,需要用OpenEvent()获得事件访问权;
如果一个线程需要等待多个事件,可使用 WaitForMultipleObjects()来等待

HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);   声明事件对象
SetEvent(event);    置位事件,让首个需要同步线程执行被保护代码
WaitForSingleObject(event, INFINITE);   等待事件置位
do something...
SetEvent(event);       事件置位

三、信号量(Semaphore)内核对象

信号量内核对象能够容许多个线程同时访问同一个资源。通过记录当前进入资源区的线程数来限制同一时间进入同一资源的线程数。
注意:
如果一个线程需要等待多个事件,可使用 WaitForMultipleObjects()来等待;
事件内核对象能够跨进程同步,需要用OpenSemaphore()获得事件访问权;

HANDLE semaphore = CreateSemaphore(NULL, 3, 3, NULL); 声明信号量对象,第一个3指的是初始计数,第二个3指的是最大计数。
WaitForSingleObject(semaphore, INFINITE);   进入信号量关口,信号量初始计数减1
do something...
ReleaseSemaphore(semaphore, 1, NULL);   释放信号量,计数加1,不得超过最大数

三、互斥(Mutex)内核对象

Mutex类似于临界区,保证多个线程对同一共享资源的互斥访问。可以跨进程通过 OpenMutex()函数得到此互斥对象的句柄。

HANDLE  mutex = CreateMutex(NULL, FALSE, NULL);     声明互斥对象。
WaitForSingleObject(mutex, INFINITE);   等待互斥对象通知,WaitForSingleObject()
do something...
ReleaseMutex(mutex);   释放互斥对象

你可能感兴趣的:(threads)