同步与互斥(多线程/多进程)
同步就是协同步调,按预定的先后次序进行运行。
同步:线程协作(直接相互制约),一个线程必须等另一线程完成某个操作后才能继续。
互斥:资源共享(间接相互制约),同一时刻仅有一个线程使用资源,是一种特殊的同步。
一、临界区(Critical Section)
同一时刻仅有一个线程可以进入临界区的代码段。
缺点:不是核心对象,不能跨进程使用。如果进入临界区的线程挂了,没有释放临界资源,系统无法获知,其他线程也无法再进入。
技巧:死锁时可以通过 CRITICAL_SECTION::OwningThread 知道进入临界区的线程号。
重入:同一线程进入临界区后再次进入,EnterCriticalSection()发现是同一线程会让其进入。
[cpp]
void InitializeCriticalSection(lpCS); //创建
BOOL TryEnterCriticalSection(lpCS); //判断可入
void EnterCriticalSection(lpCS); //进入
void LeaveCriticalSection(lpCS); //离开
void DeleteCriticalSection(lpCS); //销毁
void InitializeCriticalSection(lpCS); //创建
BOOL TryEnterCriticalSection(lpCS); //判断可入
void EnterCriticalSection(lpCS); //进入
void LeaveCriticalSection(lpCS); //离开
void DeleteCriticalSection(lpCS); //销毁
二、事件(Event)
事件有两种状态:(1)有信号状态;(2)无信号状态。
事件有两种类型:(1)手动重置:被置为信号状态后,会唤醒所有等待的线程,而且一直保持为信号状态,直到程序把它设置为无信号状态。(2)自动重置:被置为信号状态后,仅会唤醒一个等待中的线程,然后自动恢复为无信号状态,可用于同步两个线程。
优点:是核心对象,可以跨进程使用。
[cpp]
HANDLE CreateEvent(lpAttributes, bManualReset, bInitialState, lpName); //创建(可同时有信号)
HANDLE OpenEvent(dwDesiredAccess, bInheritHandle, lpName); //打开已有
BOOL SetEvent(hEvent); //置为有信号状态
BOOL ResetEvent(hEvent); //置为无信号状态
//BOOL PulseEvent(hEvent); //设为有信号再设为无信号,以便激活线程(MSDN: 功能不可靠,仅为兼容,建议不要用)
BOOL CloseHandle(hEvent); //销毁
HANDLE CreateEvent(lpAttributes, bManualReset, bInitialState, lpName); //创建(可同时有信号)
HANDLE OpenEvent(dwDesiredAccess, bInheritHandle, lpName); //打开已有
BOOL SetEvent(hEvent); //置为有信号状态
BOOL ResetEvent(hEvent); //置为无信号状态
//BOOL PulseEvent(hEvent); //设为有信号再设为无信号,以便激活线程(MSDN: 功能不可靠,仅为兼容,建议不要用)
BOOL CloseHandle(hEvent); //销毁
三、互斥体(Mutex)
功能和临界区相似,同一时刻仅有一个线程拥有该Mutex(WaitForSingleObject后ReleaseMutex之前)
缺点:花费的时间比临界区多很多。
优点:(1)是核心对象,可以跨进程使用;(2)等待一个被锁住的Mutex可以设定TIMEOUT,不会像临界区那样只能死等;(3)占用线程退出时没有释放,其他线程等待时会识别出是被舍弃状态,并可继续使用。
[cpp]
HANDLE CreateMutex(lpAttributes, bInitialOwner, lpName); //创建(可同时拥有)
HANDLE OpenMutex(dwDesiredAccess, bInheritHandle, lpName); //打开已有
DWORD WaitForSingleObject(hMutex, dwMilliseconds); //等待拥有
BOOL ReleaseMutex(hMutex); //释放拥有
BOOL CloseHandle(hMutex); //销毁
HANDLE CreateMutex(lpAttributes, bInitialOwner, lpName); //创建(可同时拥有)
HANDLE OpenMutex(dwDesiredAccess, bInheritHandle, lpName); //打开已有
DWORD WaitForSingleObject(hMutex, dwMilliseconds); //等待拥有
BOOL ReleaseMutex(hMutex); //释放拥有
BOOL CloseHandle(hMutex); //销毁
四、信号量(Semaphore)
标识可用资源数,解决生产者/消费者问题。
[cpp]
HANDLE CreateSemaphore(lpAttributes, lInitialCount, lMaximumCount, lpName); //创建
HANDLE OpenSemaphore(dwDesiredAccess, bInheritHandle, lpName); //打开已有
DWORD WaitForSingleObject(hSemaphore, dwMilliseconds); //等待拥有资源
BOOL ReleaseSemaphore(hSemaphore, lReleaseCount, lpPreviousCount); //释放资源
BOOL CloseHandle(hSemaphore); //销毁
HANDLE CreateSemaphore(lpAttributes, lInitialCount, lMaximumCount, lpName); //创建
HANDLE OpenSemaphore(dwDesiredAccess, bInheritHandle, lpName); //打开已有
DWORD WaitForSingleObject(hSemaphore, dwMilliseconds); //等待拥有资源
BOOL ReleaseSemaphore(hSemaphore, lReleaseCount, lpPreviousCount); //释放资源
BOOL CloseHandle(hSemaphore); //销毁
五、多线程计数器(原子操作)
[cpp]
LONG InterlockedIncrement(lpAddend); //增1
LONG InterlockedDecrement(lpAddend); //减1
LONGLONG InterlockedIncrement64(lpAddend); //增1
LONGLONG InterlockedDecrement64(lpAddend); //减1
LONG InterlockedIncrement(lpAddend); //增1
LONG InterlockedDecrement(lpAddend); //减1
LONGLONG InterlockedIncrement64(lpAddend); //增1
LONGLONG InterlockedDecrement64(lpAddend); //减1
补充:综合编程 , 其他综合 ,