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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 百度电视云试水搅局智能投影市场的背后

    百度电视云试水搅局智能投影市场的背后

    2021年8月31日
    58
  • 机器学习中正则化项L1和L2的直观理解

    机器学习中正则化项L1和L2的直观理解正则化(Regularization)机器学习中几乎都可以看到损失函数后面会添加一个额外项,常用的额外项一般有两种,一般英文称作ℓ1ℓ1\ell_1-norm和ℓ2ℓ2\ell_2-norm,中文称作L1正则化和L2正则化,或者L1范数和L2范数。L1正则化和L2正则化可以看做是损失函数的惩罚项。所谓『惩罚』是指对损失函数中的某些参数做一些限制。对于线性回归模型,使用L1正则化的模型建叫做…

    2022年7月13日
    20
  • JavaScript中prototype用法

    JavaScript中prototype用法1概述大部分面向对象的编程语言,都是以类class作为对象的基础语法,js语言不是如此,它的面向对象编程基于‘原型对象’。首先说说构造函数的缺点:js通过构造函数生成新的对象,因此构造函数可以视为独享的模版。实例对象的属性和方法,可以定义在构造函数内部概述构造函数的缺点JavaScript通过构造函数生成新对象,因此构造函数可以视为对象的模板。实例对象的属性和方法,可以定

    2022年7月22日
    13
  • java dom4j 增删改查[通俗易懂]

    java dom4j 增删改查[通俗易懂]packagecn.itcast.dom4j;importjava.io.FileOutputStream;importjava.io.OutputStream;importjava.util.List;importorg.dom4j.Document;importorg.dom4j.DocumentException;importorg.dom4j.Document

    2022年7月14日
    15
  • 分布式锁—-数据库和redis实现分布式锁

    分布式锁—-数据库和redis实现分布式锁

    2021年8月3日
    74
  • Java 唯一ID生成器「建议收藏」

    Java 唯一ID生成器「建议收藏」前言:   前段时间,写了一个ID生成,发在群里,结果遭到别人嘲笑,心有不甘,于是思来想去,决定在重新写一个ID生成器。此方法生成的ID理论上也是会有重复,但是这个概率太低太低,低到可以忽略不计。原理:使用当前时间戳+指定长度的随机数,并随机打乱字符串。可以生成指定长度的纯数字的ID。具体实现代码:/***普通Id生成器,用时间戳生成+2位随机数生成,*此方法

    2022年6月16日
    419

发表回复

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

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