Win32多线程 -- 线程同步之互斥器(Mutex)

CRITICAL_SECTIONMutex
InitializeCriticalSection()CreateMutex()
OpenMutex()
EnterCriticalSection()WaitForSingleObject()
WaitForMultipleObjects()
MsgWaitForMultipleObjects()
LeaveCriticalSection()ReleaseMutex()
DeleteCriticalSection()CloseHandle()

 

1. 创建Mutex

HANDLE CreateMutex(
	LPSECURITY_ATTRIBUTES lpMutexAttributes,
	BOOL bInitialOwner,	// TRUE:条用CreateMutex的线程拥有产生出来的Mutex
	LPCTSTR lpName		// Mutex名称, 其他进程或线程可以通过名称使用该Mutex
					    //  NULL Mutex没有名称
);

返回值:
调用成功,返回Mutex句柄handle,此时调用GetLastError如果返回值为ERROR_ ALREADY_EXISTS,则说明该命名的Mutex已经存在;
调用失败,返回NULL,此时GetLastError可以获得具体失败原因。
当你不再需要一个 mutex时,你可以调用CloseHandle()将它关闭.和其他核心对象一样,mutex有一个引用计数(reference count)。每次你调用CloseHandle(),引用计数便减 1。当引用计数达到 0 时, mutex 便自动被系统清除掉。

2. 锁住一个互斥器(Mutex)

欲获得一个mutex的拥有权,请使用 Win32 的 Wait...() 函数。 Wait...()对 mu tex 所做的事情和 EnterCriticalSection() 对 critical section 所做的事情差不多。
以下是获取两个Mutex的拥有权方式:
HANDLE hMutex[2]; // 假设已经创建好
方法一:
WaitForSingleObject(hMutex[0], INFINITE);
WaitForSingleObject(hMutex[1], INFINITE);
这是不安全的用法, 因为在执行完成第一行之后, 可能发生线程切换,因而产生死锁。正确应该如方法2,要么两个一起拥有,要么一个都不用有。
方法二:
WaitForMultipleObjects(hMutex, 2, INFINITE);

3. 释放Mutex拥有权

BOOL ReleaseMutex( HANDLE hMutex );
线程拥有mutex 就好像线程进入critical section 一样。一次只能有一个线程拥有该mutex。
如果线程拥有一个mutex 而在结束前没有调用 ReleaseMutex(), mutex不会被摧毁。取而代之的是,该 mutex会被视为 " 未被拥有 " 以及 " 未被激发 " ,而下一个等待中的线程会被以WAIT_ABANDONED_0 通知。不论线程是因为 ExitThread() 而结束,或是因当掉而结束,这种情况都存在。如果其他线程正以 WaitForMultipleObjects() 等待此 mutex,该函数也会返回,传回值介于 WAIT_ABANDONED_0 和 (WAIT_ABANDONED_0_n +1)之间,其中的 n 是指 handle 数组的元素个数。线程可以根据这个值了解到究竟哪一个mutex被放弃了。至于WaitForSingleObject(),则只是传回WAIT_ABANDONED_0。

4. 解决CRITICAL_SECTION的死锁问题

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

#0001 struct Node
#0002 {
#0003 	struct Node *next;
#0004 	int data;
#0005 };
#0006
#0007 struct List
#0008 {
#0009 	struct Node *head;
#0010 	HANDLE hMutex;
#0011 };
#0012
#0013 struct List *CreateList()
#0014 {
#0015 	List *list = (List *)malloc(sizeof(struct List));
#0016 	list->head = NULL;
#0017 	list->hMutex = CreateMutex(NULL, FALSE, NULL);
#0018 	return list;
#0019 }
#0020
#0021 void DeleteList(struct List *list)
#0022 {
#0023 	CloseHandle(list->hMutex);
#0024 	free(list);
#0025 }
#0026
#0027 void SwapLists(struct List *list, struct List *list2)
#0028 {
#0029 	struct List *tmp_list;
#0030 	HANDLE arrhandles[2];
#0031
#0032 	arrhandles[0] = list1->hMutex;
#0033 	arrhandles[1] = list2->hMutex;
#0034 	WaitForMultipleObjects(2, arrHandles, TRUE, INFINITE);
#0035 	tmp_list = list1->head;
#0036 	list1->head = list2->head;
#0037 	list2->head = tmp_list;
#0038 	ReleaseMutex(arrhandles[0]);
#0039 	ReleaseMutex(arrhandles[1]);
#0040 }

5. Question

5.1 Mutex能否如下使用:

Mutex能否如下使用:
void function()
{
	WaitForMultipleObjects(hMutex, 1, INFINITE);
	// do something
	{
		WaitForMultipleObjects(hMutex, 1, INFINITE);
		// do something
		ReleaseMutex(hMutex);
	}
	ReleaseMutex(hMutex);
}
以上程序会死锁吗?

5.2 Mutex解决哲学家进餐问题

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值