您的位置:首页 > 移动开发 > Objective-C

CreateMutex、WaitForSingleObject、ReleaseMutex——创建互斥对象

2016-02-17 14:54 513 查看
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;
}



运行结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: