releasemutex
CreatemutexCreateMutex作用是找出当前系统是否已经存在指定进程的实例。如果没有则创建一个互斥体。
互斥对象是系统内核维护的一种数据结构,它保证了对象对单个线程的访问权 互斥对象的结构:包含了一个使用数量,一个线程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;
// 程序退出
};
//上面这段代码演示了有名互斥量在进程互斥中的用法。代码的核心是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;
}
运行结果: