windows核心编程-互斥器(Mutexes)

线程同步的方式主要有:临界区、互斥区、事件、信号量四种方式。
前边讲过了临界区线程同步-----windows核心编程-关键段(临界区)线程同步,这章我来介绍一下互斥器(Mutexes)在线程同步中的使用。
互斥器(Mutexes)的用途和临界区(critical section)的用途非常相似,如:一个时间内只能够有一个线程拥有mutex,就好像同一时间内只能够有一个线程进入同一个critical section一样。但是mutex通过牺牲速度,提高了灵活性,功能变得更加强大了。

虽然mutex和critical section做相同的事情,但它们的运作还是有差别的:
1、锁住一个未被拥有的mutex,比锁住一个未被拥有的critical section需要花费几乎100倍的时间。
2、mutex可以跨进程使用。critical section则只能在同一个进程中使用。

3、等待一个mutex时,你可以指定“结束等待”的世间长度,但对于critical section则不行。


造成以上差别的主要原因是:mutex是内核对象,critical section非内核对象。

以下是mutex和critical section的相关函数比较:

临界区 互斥器
CRITICAL_SECTION
InitializeCriticalSection()
CreateMutex()
OpenMutex()
EnterCriticalSection() WaitForSingleObject()
WaitForMultipleObjects()
MsgWaitForMultipleObjects()
LeaveCriticalSection() ReleaseMutex()
DeleteCriticalSection() CloseHandle()

使用mutex时注意:

在一个适当的程序中,线程绝对不应该在它即将结束前还拥有一个mutex,因为这意味着线程没有能够适当地清除其资源。不幸的是,我们并不身处一个完美的世界,有时候,因为某种理由,线程可能没有在结束前调用ReleaseMutex()。为了解决这个问题,mutex有一个非常重要的特性。这性质在各种同步机制中是独一无二的,如果线程拥有一个mutex而在结束前没有调用ReleaseMutex(),mutex不会被摧毁,取而代之的是,该mutex会被视为“未被拥有”以及“未被激发”,而下一个等待中的线程会被以WAIT_ABANDONED_0通知。无论线程是因为ExitThread()而结束,或是因当掉而结束,这种情况都存在。


任何时候只要你想锁住超过一个以上的同步对象,你就有死锁的潜在病因。
如果总是在相同时间把所有对象都锁住,问题可去矣。
事例如下,存在潜在死锁的可能:

void SwapLists(List* list1, List* list2)
{
	EnterCriticalSection(list1->critical_sec);
	EnterCriticalSection(list2->critical_sec);
	//list1,list2数据交换
	LeaveCriticalSection(list1->critical_sec);
	LeaveCriticalSection(list2->critical_sec);
}
正确的做法:
void SwapLists(List* list1, List* list2)
{
	HANDLE arrHandles[2];
	arrHandles[0] = list1->hMutex;
	arrHandles[1] = list2->hMutex;
	WaitForMultipleObjects(2, arrHandles, TRUE, INFINITE);
	//list1,list2数据交换
	ReleaseMutex(arrHandles[0]);
	ReleaseMutex(arrHandles[1]);
}
信号量的介绍----- windows核心编程-信号量(semaphore)

你可能感兴趣的:(windows核心编程-互斥器(Mutexes))