大家好,又见面了,我是你们的朋友全栈君。
CreateMutex
CreateMutex作用是找出当前系统是否已经存在指定进程的实例。如果没有则创建一个互斥体。
互斥对象是系统内核维护的一种数据结构,它保证了对象对单个线程的访问权 互斥对象的结构:包含了一个使用数量,一个线程ID,一个计数器 使用数量是指有多少个线程在调用该对象,线程ID是指互斥对象维护的线程的ID 计数器表示当前线程调用该对象的次数
声明
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTESlpMutexAttributes, // 指向安全属性的指针
BOOLbInitialOwner, // 初始化互斥对象的所有者
LPCTSTRlpName // 指向互斥对象名的指针
);
说明
创建一个互斥体(MUTEX)
返回值
Long,如执行成功,就返回互斥体对象的句柄;零表示出错。会设置GetLastError。即使返回的是一个有效句柄,但倘若指定的名字已经存在,GetLastError也会设为ERROR_ALREADY_EXISTS
参数表
参数 类型及说明lpMutexAttributes SECURITY_ATTRIBUTES,指定一个SECURITY_ATTRIBUTES结构,或传递零值(将参数声明为ByVal As Long,并传递零值),表示使用不允许继承的默认描述符
bInitialOwner Long,如创建进程希望立即拥有互斥体,则设为TRUE。一个互斥体同时只能由一个线程拥有
lpName String,指定互斥体对象的名字。用vbNullString创建一个未命名的互斥体对象。如已经存在拥有这个名字的一个事件,则打开现有的已命名互斥体。这个名字可能不与现有的事件、信号机、可等待计时器或文件映射相符它的具体作用是每调用它一次将互斥对象的计数器减一,直到减到零为止,此时释放互斥对象,并将互斥对象中的线程id 置零。 它的使用条件是,互斥对象在哪个线程中被创建,就在哪个线程里面释放。因为调用的时候会检查当前线程的id是不是与互斥对象中保存的id一致,若一致,则此次操作有效,不一致,则无效。
注解编辑
一旦不再需要,注意必须用CloseHandle函数将互斥体句柄关闭。从属于它的所有句柄都被关闭后,就会删除对象线程中止前,一定要调用ReleaseMutex释放互斥体,如不慎未采取这个措施,就会将这个互斥体标记为废弃(下一个释放的等待函数会返回WAIT_ABANDONED),并自动释放所有权。共享这个互斥体的其他应用程序也许仍
然能够用它,但会接收到一个废弃状态信息,指出上一个所有进程未能正常关闭。这种状况是否会造成影响取决于涉及到的具体应用程序。在Windows系统中,线程可以在等待函数中指定一个此线程已经拥有的互斥体,由于Windows的防死锁机制,这种做法不会阻止此线程的运行。
使用例子编辑
常用操作mutex的函数还有:ReleaseMutex/OpenMutex/WaitForSingleObject/WaitForMultipleObjects。
创建互斥体
h_mutex1=CreateMutex(NULL,FALSE,”mutex_for_readcount”);//创建一个互斥体
检查错误代码
#include <stdio.h>
#include <windows.h>
…… // main function
HANDLE m_hMutex = CreateMutex(NULL, FALSE, “Sample07”);// 检查错误代码
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
// 如果已有互斥量存在则释放句柄并复位互斥量
CloseHandle(m_hMutex);
m_hMutex = NULL;
// 程序退出
return FALSE;
};//上面这段代码演示了有名互斥量在进程互斥中的用法。代码的核心是CreateMutex()对有名互斥量的创建。CreateMutex() 用于有独占要求的程序 (在其进程运行期间不允许其他使用此端口设备的程序运行,或不允许同名程序运行)。
详细例子
下面这段代码详细介绍了CreateMutex函数的使用方法:
#include “stdafx.h”#include “windows.h”int main(int argc, char* argv[]){ HANDLE m_hMutex = CreateMutex(NULL,TRUE,”cplusplus_me”); DWORD dwRet = GetLastError(); if (m_hMutex) { if (ERROR_ALREADY_EXISTS == dwRet) { printf(“程序已经在运行中了,程序退出!\n”); CloseHandle(m_hMutex); return 0; } } else { printf(“创建互斥量错误,程序退出!\n”); CloseHandle(m_hMutex); return 0; } while(1) { printf(“cplusplus_me\n”); } CloseHandle(m_hMutex); return 0;}
WaitForSingleObject函数的使用
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
等待函数可使线程自愿进入等待状态,直到一个特定的内核对象变为已通知状态为止。
第一个参数hObject标识一个能够支持被通知/未通知的内核对象(前面列出的任何一种对象都适用)。
第二个参数dwMilliseconds允许该线程指明,为了等待该对象变为已通知状态,它将等待多长时间。(INFINITE为无限时间量,INFINITE已经定义为0xFFFFFFFF(或-1))
传递INFINITE有些危险。如果对象永远不变为已通知状态,那么调用线程永远不会被唤醒,它将永远处于死锁状态,不过,它不会浪费宝贵的C P U时间。
ReleaseMutex
BOOL WINAPI ReleaseMutex(HANDLE hMutex);
一个线程释放了互斥对象的控制权后,如果其他进程在等待互斥对象置位,则等待的线程可以得到该互斥对象,等待函数返回,互斥对象被新的线程所拥有。
实例代码
<pre name=”code” class=”cpp”>#include “stdafx.h”#include <iostream>#include <windows.h>#include <process.h>using namespace std; HANDLE hMutex; UINT __stdcall Add(LPVOID lParam){ DWORD dReturn = WaitForSingleObject(hMutex, INFINITE); for (int i = 0; i < 10; i++) { cout << i << ” “; } cout << endl; cout << “Add end\n” << endl; ReleaseMutex(hMutex); return 1;} UINT __stdcall Add2(LPVOID lParam){ DWORD dReturn = WaitForSingleObject(hMutex, INFINITE); for (int i = 100; i < 110; i++) { cout << i << ” “; } cout << endl; cout << “Add2 end\n” << endl; ReleaseMutex(hMutex); return 1;} void Add3(LPVOID lParam){ DWORD dReturn = WaitForSingleObject(hMutex, INFINITE); for (int i = 1000; i < 1010; i++) { cout << i << ” “; } cout << endl; cout << “Add3 end\n” << endl; ReleaseMutex(hMutex);} typedef UINT(__stdcall *PTHREAD_HANDLE)(void*);int _tmain(int argc, _TCHAR* argv[]){ hMutex = CreateMutex(NULL, FALSE, (LPCWSTR)””); HANDLE hUp; hUp = (HANDLE)_beginthreadex(NULL, NULL, Add, NULL, NULL, 0); hUp = (HANDLE)_beginthreadex(NULL, NULL, Add2, NULL, NULL, 0); hUp = (HANDLE)_beginthreadex(NULL, NULL, (PTHREAD_HANDLE)Add3, NULL, NULL, 0); Sleep(60 * 1000); return 0;}
运行结果:
原文:https://blog.csdn.net/nie2314550441/article/details/50679519
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/153176.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...