互斥锁的使用(CreateMutex等使用)

1.CreateMutex函数原型

HANDLE CreateMutex(
 LPSECURITY_ATTRIBUTES lpMutexAttributes, // 指向安全属性的指针
 BOOL bInitialOwner, // 初始化互斥对象的所有者,如果希望进程立即拥有互斥体则设为FALSE
 LPCTSTR lpName // 指向互斥对象名的指针
);

功能:创建一个互斥体(MUTEX)

  1. CreateMutex只是创建了一把锁, 这把锁你用来锁门还是锁抽屉还是锁你对象的内裤都由你自己决定。
  2. lpName是指定这把锁的名字. 你要不给这把锁取个名字都可以. 只是有了相同的名字, 在跨进程加锁的时候, 就可以得到同一把锁。
  3. HANDLE m_hMutex = CreateMutex(NULL,TRUE,“cplusplus_me”); 只是创建了一把锁, 到目前这句完成, 他没有锁任何东西。

    如果函数成功执行,将返回一个互斥量对象的句柄。如果在CreateMutex()执行前已经存在有相同名字的互斥量,函数将返回这个已经存在互斥量的句柄,并且可以通过GetLastError()得到错误代码ERROR_ALREADY_EXIST。可见,通过对错误代码ERROR_ALREADY_EXIST的检测可以实现CreateMutex()对进程的互斥。

通过这个性质,就可以做一个避免进程重复打开的功能。
部分代码如下:

HANDLE m_hMutex = CreateMutex(NULL, FALSE, "Sample07");// 创建互斥量
if (GetLastError() == ERROR_ALREADY_EXISTS)
  {
  // 如果已有互斥量存在则释放句柄并复位互斥量 
  CloseHandle(m_hMutex);
  m_hMutex = NULL;
  // 程序退出
  return FALSE;
  };

2.WaitForSingleObject的理解

请看:关于WaitForSingleObject的理解

3.CreateMutex和WaitForSingleObject的配合使用

3.1如何加锁

一般使用WaitForSingleObject(hMutex, INFINITE); 加锁

3.2如何解锁

一般使用ReleaseMutex(hMutex);解锁

这里写被加锁的东西. 一般是操作一些共享数据(占用系统内存)。

4.使用示例

问题:
假设 一个剧团卖票 一共10章票,3个电脑在卖它,每个人选座位买票大约花费500ms。模拟这样的场景,输出顺序是按购买顺序。

HANDLE hMutex = NULL;
//共享资源
static int num = 0; //目前一张都没卖出去

#define NUMSIZE 10 //num最大是10 可以更改

//子线程函数
unsigned long __stdcall ChildThreadFunc1(LPVOID pM)
{
while(num<NUMSIZE)
{
	Sleep(500); //花500ms选取位置支付等过程
	//加锁
	WaitForSingleObject(hMutex, INFINITE);//等待互斥量 
	if(num<NUMSIZE)
	{ 
		num++;
		printf("ThreadFunc1 num:%d\n", num);
	}
	//解锁
	ReleaseMutex(hMutex); //执行完放弃对数据的所有权
}
return 0;

}
//子线程函数
unsigned long __stdcall ChildThreadFunc2(LPVOID pM)
{
while (num < NUMSIZE)
{
Sleep(500);
//加锁
WaitForSingleObject(hMutex, INFINITE);//等待互斥量
if (num<NUMSIZE)
{
num++;
printf(“ThreadFunc2 num:%d\n”, num);
}
//解锁
ReleaseMutex(hMutex); //执行完放弃对数据的所有权
}
return 0;
}
//子线程函数
unsigned long __stdcall ChildThreadFunc3(LPVOID pM)
{
while (num <NUMSIZE)
{
//加锁
Sleep(500);
WaitForSingleObject(hMutex, INFINITE);//等待互斥量
if (num<NUMSIZE)
{
num++;
printf(“ThreadFunc3 num:%d\n”, num);
}
//解锁
ReleaseMutex(hMutex); //执行完放弃对数据的所有权
}
return 0;
}

int main()
{
hMutex = CreateMutex(NULL,/*指向安全属性的指针*/
					FALSE,/*初始化互斥对象的所有者 如果希望进程立即拥有互斥体则设为FALSE*/ 
					NULL);/*指向互斥对象名的指针*/
HANDLE handle[3] = { 0 };
handle[0] = CreateThread(NULL, 0, ChildThreadFunc1, NULL, 0, NULL);
handle[1] = CreateThread(NULL, 0, ChildThreadFunc2, NULL, 0, NULL);
handle[2] = CreateThread(NULL, 0, ChildThreadFunc3, NULL, 0, NULL);

//阻塞等待
Sleep(8000);

printf("主线程 num:%d\n", num);
for (int i = 0; i < 3; i++)
{
	CloseHandle(handle[i]);
}
CloseHandle(hMutex);
system("pause");
return 0;

}

运行结果:
在这里插入图片描述

5.注意

有如下代码:
在这里插入图片描述
运行结果是不是有点吃惊,其实你停下来仔细想想也就通了,每个进程本来就有一个主线程。因为你创建的mutex一开始没有拥有者,所以第一次WaitForSingleObject会使当前线程获得mutex的所有权,并立即返回
mutex的所有线程再次等待mutex时也不会阻塞,因此第二次WaitForSingleObject也会马上返回,因为你是在同一个线程中调用WaitForSingleObject的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

发如雪-ty

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值