C++多线程编程:同步之互斥量Mutex「建议收藏」

C++多线程编程:同步之互斥量Mutex「建议收藏」文章目录5.示例代码文章目录1.CreateMutex()2.ReleaseMutex()3.WaitForSingleobject()4.CloseHandle()5.示例代码6.Mutex实现一个程序只允许允许一个实例(进程)5.示例代码文章目录1.CreateMutex()2.ReleaseMutex()3.WaitForSingleobject()4.CloseHandle()5.示例代码6.Mutex实现一个程序只允许允许一个实例(进程))5.示例代码文章目录1

大家好,又见面了,我是你们的朋友全栈君。

C++使用内核对象互斥体(Mutex)来实现线程同步锁。当两个或更多线程需要同时访问一个共享资源时,Mutex可以只向一个线程授予对共享资源的独占访问权。如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。

1. CreateMutex()

https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createmutexa

HANDLE CreateMutexA(
 LPSECURITY_ATTRIBUTES lpMutexAttributes,
 BOOL                  bInitialOwner,
 LPCSTR                lpName
);

2. ReleaseMutex()

https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-releasemutex

BOOL ReleaseMutex(
 HANDLE hMutex
);

3. WaitForSingleobject()

https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject

DWORD WaitForSingleObject(
 HANDLE hHandle,
 DWORD  dwMilliseconds
);

该函数需要传递一个内核对象句柄,如果该内核对象处于未通知状态,则该函数导致线程进入阻塞状态;如果该内核对象处于已通知状态,则该函数立即返回 WAIT_OBJECT()第二个参数指明要等待的时间(毫秒),INFINITE表示无限等待,如果第二个参数为0,那么函数立即返回。如果等待超时,该函数返 WAIT_TIMEOUT如果该函数失败,返回 WAIT_FAILED。

该函数需要传递一个内核对象句柄,如果该内核对象处于未通知状态,则该函数导致线程进入阻塞状态;如果该內核对象处于已通知状态,则该函数立即返回 WAIT_OBJECT()。第二个数指明要等待的时间(毫秒),INFINITE表示无限等待,如果第二个参数为0,那么函数立即返回。如果等待超时,该函数返 WAIT_TIMEOUT。
如果该函数失败,返回 WAIT_FAILED

4. CloseHandle()

https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle

BOOL CloseHandle(
 HANDLE hObject
);

5. 示例代码

#include<process.h>
#include<windows.h>
#include<stdio.h>


void    __cdecl   SellThread1(void* param);
void    __cdecl   SellThread2(void* param);

//100张票
int   tickets = 100;


HANDLE  hMutex = INVALID_HANDLE_VALUE;

int  main()
{ 
    

   //创建互斥体,此刻为有信号状态
   hMutex = CreateMutex(NULL, FALSE, L"售票互斥体");
    

   printf("开始卖票了!\n");

   //创建两个售票窗口 
   uintptr_t   t1 = _beginthread(SellThread1, 0, "售口窗口A");
   uintptr_t   t2 = _beginthread(SellThread2, 0, "售口窗口B");

   //无限等待两个线程全部执行完毕
   HANDLE  hArr[] = { 
    (HANDLE)t1,  (HANDLE)t2 };
   WaitForMultipleObjects(2, hArr, true, INFINITE);

   printf("卖票结束!\n");
    

   return 0;
}


void    __cdecl   SellThread1(void* param)
{ 
   
   char  *name = (char *)param;

   while (tickets>0)
   { 
   
   	//如果这个互斥体为有信号状态(没有线程拥有它),则线程获取它后继续执行
   	WaitForSingleObject(hMutex, INFINITE);
   	 if (tickets > 0)
   	{ 
   
   		Sleep(10);
   		//CPU恰好执行到这里,这个时候线程时间片到了,并且此时还剩最后一张票
   		printf("%s卖出第%d张票!\n", name, tickets--);
   	} 
   	 //释放对互斥体的拥有权,它变成有信号状态
   	 ReleaseMutex(hMutex);

   }


}
void    __cdecl   SellThread2(void* param)
{ 
   
   char  *name = (char *)param;


   while (tickets > 0)
   { 
   
   	//如果这个互斥体为有信号状态(没有线程拥有它),则线程获取它后继续执行
   	WaitForSingleObject(hMutex, INFINITE);
       	if (tickets > 0)
   		{ 
   
   			Sleep(10);
   			//CPU恰好执行到这里,这个时候线程时间片到了,并且此时还剩最后一张票
   			printf("%s卖出第%d张票!\n", name, tickets--);
   		}
   	 //释放对互斥体的拥有权,它变成有信号状态
   	 ReleaseMutex(hMutex);
   }
}

6. Mutex实现一个程序只允许允许一个实例(进程)

#include<process.h>
#include<windows.h>
#include<stdio.h>

int  main()
{ 
   
   //创建互斥体实现一个程序只允许允许一个实例(进程)
   HANDLE  hMutex   = CreateMutex(NULL, FALSE, L"售票互斥体");
   if (GetLastError() == ERROR_ALREADY_EXISTS)
   { 
   
   	printf("程序已经运行了,退出!\n");
   	getchar();

   	CloseHandle(hMutex);
   	return  0;
   }

   printf("第一次运行程序!\n");
   getchar();

   return 0;
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/153213.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 中间件

    我们在开发中经常会遇到判断用户是否登录,把没有登录的用户请求跳转到登录页面。我们通常会通过给几个特定视图函数加装饰器实现了这个需求。但是以后添加的视图函数能也需要加上装饰器,这样是不是稍微有点繁琐;

    2022年3月29日
    36
  • Java中有哪些集合,集合中有哪些类?

    Java中有哪些集合,集合中有哪些类?Java中所有的类都位于java.util包下,主要由两个接口派生出来,分别是Collection和Map.Collection包含了List和Set两大分支。Map是一个映射接口。Set、Map、List可以看做集合的三大类。而遍历集合的工具有Iterator和Enumeration;Arrays和Collection是操作数组集合的两个工具类。一、Java中的集合主要分为四类:1、L…

    2022年7月7日
    22
  • java中的适配器是什么及有什么作用(通熟易懂)

    java中的适配器是什么及有什么作用(通熟易懂)其实适配器只是一个类,它实现了某种接口,提供了方法体。这样,再用到这个接口时,可以直接继承适配器,这样就不需要把接口中的每一个方法再填充一遍了,只需要在这个类中复写一下需要用的方法。这样简单,方便。这只是一个简化编程的模式,举个例子,比如java的鼠标监听接口有七个方法,但是往往我们要处理的只是其中一两个方法,但是实现这个接口就必须为了java语法而去重写七个方法,这是毫无意义的,

    2022年6月3日
    38
  • Java中的八种基本数据类型「建议收藏」

    Java中的八种基本数据类型「建议收藏」Java中主要有八种基本数据类型:byte、short、int、long、float、double、boolean、char。各种数据类型作用:1、byte:8位、有符号的以二进制补码表示的整数。min:-128(-2^7)。max:127(2^7-1)。default:0。对应包装类:Byte。2、short:16位…

    2022年7月7日
    16
  • idea安装下载「建议收藏」

    idea安装下载「建议收藏」idea安装下载

    2022年4月21日
    50
  • uva 12230 – Crossing Rivers(概率)「建议收藏」

    uva 12230 – Crossing Rivers(概率)

    2022年1月21日
    34

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号