c++通过互斥量实现单例模式

在工程文件中, WinMain函数里加上以下代码

[cpp] view
plain
copy

  1. HANDLE hMutex = CreateMutex(NULL, false, "Process");
  2. if (GetLastError() == ERROR_ALREADY_EXISTS)
  3. {
  4. CloseHandle(hMutex);
  5. MessageBox(Application->Handle, "程序已经在运行中,不能重复启动!", "提示", MB_OK +MB_ICONWARNING);
  6. Application->Terminate();
  7. return 0;
  8. }
  9. Application->CreateForm(__classid(TForm1), &Form1);

主要使用到CreateMutex()函数和GetLastError()以及一个常量ERROR_ALREADY_EXISTS.

当然, 你的程序有窗体的话, 还可以使用FindWindow().

[cpp] view
plain
copy

  1. void *handle = FindWindow(NULL, WindowName.c_str());
  2. if (handle!=NULL)
  3. return 0;

进程的互斥运行

  正常情况下,一个进程的运行一般是不会影响到其他正在运行的进程的。但是对于某些有特殊要求的如以独占方式使用串行口等硬件设备的程序就要求在其进程运行期间不允许其他试图使用此端口设备的程序运行的,而且此类程序通常也不允许运行同一个程序的多个实例。这就引出了进程互斥的问题。

  实现进程互斥的核心思想比较简单:进程在启动时首先检查当前系统是否已经存在有此进程的实例,如果没有,进程将成功创建并设置标识实例已经存在的标记。此后再创建进程时将会通过该标记而知晓其实例已经存在,从而保证进程在系统中只能存在一个实例。具体可以采取内存映射文件、有名事件量、有名互斥量以及全局共享变量等多种方法来实现。下面就分别对其中具有代表性的有名互斥量和全局共享变量这两种方法进行介绍:

[cpp] view
plain
copy

  1. // 创建互斥量
  2. HANDLE m_hMutex = CreateMutex(NULL, FALSE, "Sample07");
  3. // 检查错误代码
  4. if (GetLastError() == ERROR_ALREADY_EXISTS) {
  5.  // 如果已有互斥量存在则释放句柄并复位互斥量
  6.  CloseHandle(m_hMutex);
  7.  m_hMutex = NULL;
  8.  // 程序退出
  9.  return FALSE;
  10. }

上面这段代码演示了有名互斥量在进程互斥中的用法。代码的核心是CreateMutex()对有名互斥量的创建。CreateMutex()函数可用来创建一个有名或无名的互斥量对象,其函数原型为:

[cpp] view
plain
copy

  1. HANDLE CreateMutex(
  2.  LPSECURITY_ATTRIBUTES lpMutexAttributes, // 指向安全属性的指针
  3.  BOOL bInitialOwner, // 初始化互斥对象的所有者
  4.  LPCTSTR lpName // 指向互斥对象名的指针
  5. );

如果函数成功执行,将返回一个互斥量对象的句柄。如果在CreateMutex()执行前已经存在有相同名字的互斥量,函数将返回这个已经存在互斥量的句柄,并且可以通过GetLastError()得到错误代码ERROR_ALREADY_EXIST。可见,通过对错误代码ERROR_ALREADY_EXIST的检测可以实现CreateMutex()对进程的互斥。

建立互斥体,用来同步。如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。

参数

lpMutexAttributes

指向一个SECURITY_ATTRIBUTES结构的指针,这个结构决定互斥体句柄是否被子进程继承。

bInitialOwner

布尔类型,决定互斥体的创建者是否为拥有者

lpName

指向互斥体名字字符串的指针。互斥体可以有名字。

互斥体的好处是可以在进程间共享

心得体会:

CreateMutex() 用于有独占要求的程序 (在其进程运行期间不允许其他使用此端口设备的程序运行,或不允许同名程序运行)。如有同名程序运行,则通过 GetLastError()得到错误代码 ERROR_ALREADY_EXIST。

刚才又执行了下得出的结果(程序名samp)

一般情况下:一进入调试阶段,进程管理器中就出现了samp进程,执行到CreateMutex时返回进程句柄,执行到if(GetLastError() == ERROR_ALREADY_EXISTS ) 进行判断时,跳过不执行if中的内容,所以表示没有互斥。

调试之前先运行debug中的samp.exe再调试:一进入调试阶段,进程管理器中就出现了两个samp进程,执行到CreateMutex时返回进程句柄,执行到if(GetLastError() == ERROR_ALREADY_EXISTS ) 进行判断时,执行if中的内容,表示有互斥

我们公司的使用方法为

[cpp] view
plain
copy

  1. HANDLE NetIq::CreateMutexNetIq()
  2. {
  3. HANDLE nMutex = NULL;
  4. std::string strDeployRole = NetClient::Instance().m_strDeployRole;
  5. std::string strMutexId = Utils::String::Format("%s%s", NetIQ::Configure::Instance().m_strGuid.c_str(), strDeployRole.c_str());
  6. nMutex = ::CreateMutex(NULL, FALSE, strMutexId.c_str());
  7. if( NULL != nMutex )
  8. {
  9. DWORD dwErrorCode = ::GetLastError();
  10. if( ERROR_ALREADY_EXISTS == dwErrorCode )
  11. {
  12. __ULOG_INFO(__ULOG_FMT("App", "Mutex (%s) exists"), strMutexId.c_str());
  13. std::string strTitle;
  14. if( !RegisterKey::Instance().Read("", "Title", strTitle) )//读取注册表中的项目窗口名,,以便在以下将其显示。国。
  15. {
  16. return NULL;
  17. }
  18. // instance exist
  19. HWND hAppWindow = ::FindWindow(NULL, strTitle.c_str());
  20. if( NULL != hAppWindow )
  21. {
  22. ::ShowWindow(hAppWindow, SW_SHOWNORMAL);
  23. ::SetWindowPos(hAppWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
  24. ::SetWindowPos(hAppWindow, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
  25. }
  26. return NULL;
  27. }
  28. }
  29. return nMutex;
  30. }

c++通过互斥量实现单例模式,布布扣,bubuko.com

时间: 2024-11-20 16:15:48

c++通过互斥量实现单例模式的相关文章

秒杀多线程第十五篇 关键段,事件,互斥量,信号量的“遗弃”问题

版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 秒杀多线程第十五篇 关键段,事件,互斥量,信号量的“遗弃”问题 在<秒杀多线程第九篇 经典线程同步总结 关键段 事件 互斥量 信号量>中对经典多线程同步互斥问题进行了回顾和总结,这篇文章对Windows系统下常用的线程同步互斥机制——关键段.事件.互斥量.信号量进行了总结.有网友问到互斥量能处理“遗弃”问题,事件和信号量是否也能处理“遗弃”问题.因此本文将对事件和信号量作个试验,看看事件和信号量能否处理“遗弃”问题. 一.

理解互斥量和信号量

互斥量(Mutex) 互斥量表现互斥现象的数据结构,也被当作二元信号灯.一个互斥基本上是一个多任务敏感的二元信号,它能用作同步多任务的行为,它常用作保护从中断来的临界段代码并且在共享同步使用的资源. Mutex本质上说就是一把锁,提供对资源的独占访问,所以Mutex主要的作用是用于互斥.Mutex对象的值,只有0和1两个值.这两个值也分别代表了Mutex的两种状态.值为0, 表示锁定状态,当前对象被锁定,用户进程/线程如果试图Lock临界资源,则进入排队等待:值为1,表示空闲状态,当前对象为空闲

信号量、互斥量、同步变量、条件变量和事件变量

信号量:信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用.在进入一个关键代码段之前,线程必须获取一个信号量:一旦该关键代码段完成了,那么该线程必须释放信号量.其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量.为了完成这个过程,需要创建一个信号量VI,然后将Acquire Semaphore VI以及Release Semaphore VI分别放置在每个关键代码段的首末端.确认这些信号量VI引用的是初始创建的

线程同步---互斥量mutex

1. 问题引入:开两个线程同时对一个全局变量10万次做自加,结果会如何? #include <stdio.h> #include <string.h> #include <pthread.h> unsigned int g_cn = 0; void* thread_proc (void* arg) { unsigned int i; for (i = 0; i < 100000; i++) ++g_cn; return NULL; } int main (void

线程------竞争,互斥量---多线程对同一文件读写问题

当多个控制线程共享相同的内存时呢,需要确保每个线程看到一致的数据视图. 如果每个线程使用的变量都是其他线程不会读取和修改,那么就不存在一致性的问题. 线程互斥接口用来保护数据,用于确保同一时间只有一个线程访问数据. 互斥:限制代码---独占 很久以前: 下面程序存在竞争问题的哟,当创建20个线程,每个线程都对同一个文件进行读写操作,有可能发生N个线程同时对文件进行打开和读操作,在写的过程可能会对同一个数重复进行+1操作.比如说读到  1, 然后N个线程取到1 并对1这个数做+1操作. /* 实现

互斥量函数

一.互斥锁互斥锁,是一种信号量,常用来防止两个进程或线程在同一时刻访问相同的共享资源.需要的头文件:pthread.h互斥锁标识符:pthread_mutex_t (1)互斥锁初始化:函数原型: int pthread_mutex_init (pthread_mutex_t* mutex,const pthread_mutexattr_t* mutexattr);函数传入值:  mutex:互斥锁.mutexattr:PTHREAD_MUTEX_INITIALIZER 创建快速互斥锁.PTHRE

数据共享之互斥量mutex

互斥量介绍 互斥量可以保护某些代码只能有一个线程运行这些代码.如果有个线程使用互斥量执行某些代码,其他线程访问是会被阻塞,直到这个线程执行完这些代码,其他线程才可以执行. 一个线程在访问共享数据前,给互斥量上锁,这时其他线程再给互斥量上锁会阻塞直到这个线程给互斥量解锁. 互斥量是C++中最常用的数据保护机制,但是它也不万能的.在编写代码时,合理的组织代码来避免资源竞争非常重要.使用互斥量可能会带来其他问题,比如死锁. 在C++中使用互斥量 创建互斥量使用mutex,给互斥量上锁使用函数lock(

C++11多线程编程之互斥量

+(UIImage*)createImageFromView:(UIView*)view { //obtain scale CGFloat scale = [UIScreen mainScreen].scale; 开始绘图,下面方法,第一个参数表示区域大小.第二个参数表示是否是非透明的.如果需要显示半透明效果,需要传NO,否则传YES.第三个参数就是屏幕密度了 UIGraphicsBeginImageContextWithOptions(CGSizeMake(view.frame.size.wi

临界区、互斥量、事件、信号量四种方式

临界区(Critical Section).互斥量(Mutex).信号量(Semaphore).事件(Event)的区别 1.临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问.在任意时刻只允许一个线程对共享资源进行访问,如果有多个线程试图访问公共资源,那么在有一个线程进入后,其他试图访问公共资源的线程将被挂起,并一直等到进入临界区的线程离开,临界区在被释放后,其他线程才可以抢占. 2.互斥量:采用互斥对象机制. 只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥