注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

对Windows下Mutex处理的注意点  

2015-08-11 17:54:26|  分类: C++(VC)编程 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

WindowsMutex处理的注意点

 

上面在处理事件的时候儿提到了类似于NOTICENALL这个动作的事件处理方法,其实这个在阻塞队列里用得着。但是昨天同事在看别人写的代码时,对Windows下的Mutex的处理方法进行了验证。

老规矩,先上代码:

HANDLE hMutex;

//HANDLE hMutex =  CreateMutex(NULL, FALSE, _T("A"));

 

TestMutex::TestMutex(void)

{

         hMutex = CreateMutex(NULL, TRUE, NULL);

}

 

 

TestMutex::~TestMutex(void)

{

 

}

 

void TestMutex::StartThread()

{

         DWORD threadID3;

         HANDLE hThread3 = CreateThread(NULL, 0, ThreadTest, this, 0, &threadID3);

         Sleep(100);

 

         DWORD threadID1;

         HANDLE hThread1 = CreateThread(NULL, 0, Thread1, this, 0, &threadID1);

         Sleep(100);

 

         DWORD threadID2;

         HANDLE hThread2 = CreateThread(NULL, 0, Thread2, this, 0, &threadID2);

 

 

 

}      

 

DWORD WINAPI TestMutex::Thread1(LPVOID param)

{

         TestMutex *p = (TestMutex*)param;

         Sleep(1000*2);

         //DWORD ret = WaitForSingleObject(p->hMutex, 30000);

         DWORD ret = WaitForSingleObject(hMutex, INFINITE);

         //Sleep(1000*5);

         //ReleaseMutex(p->hMutex);

 

         return 0;

}

 

DWORD WINAPI TestMutex::Thread2(LPVOID param)

{

         TestMutex *p = (TestMutex*)param;

         Sleep(1000*2);

         //DWORD ret =WaitForSingleObject(p->hMutex, INFINITE);

         DWORD ret =WaitForSingleObject(hMutex, INFINITE);

 

         //ReleaseMutex(hMutex);

 

         return 0;

}

 

DWORD WINAPI TestMutex::ThreadTest(LPVOID param)

{

         HANDLE handle = OpenMutex(MUTEX_ALL_ACCESS, FALSE, _T("A"));

         //HANDLE handle = NULL;//OpenMutex(MUTEX_ALL_ACCESS, FALSE, _T("A"));

         TestMutex *p = (TestMutex*)param;

         if(handle)

         {

                   int i = GetLastError();

                   int res = i;

         }

         //getchar();

         //DWORD ret =WaitForSingleObject(p->hMutex, 30000);

         DWORD ret =WaitForSingleObject(hMutex, 30000);

         //Sleep(1000*5);

 

         //ReleaseMutex(p->hMutex);

         //ReleaseMutex(hMutex);

 

         return 0;

}

 

验证的结果发现了一个问题,那就是如果在ReleaseMutex后(第二个参数为FALSE),所有的等待线程都启动了起来。那这玩意儿不就类似于LINUX下和标准C++11中的条件变量中的NoticeAll这个函数么。

其实认真看过了代码和MSDN发现了一个问题,这些个Mutex是在WaitforSingleObject时(第一个)自动获取状态,然后进入执行,其它的无法得到,就得等待了,这和事件和信号的区别就在于此,信号和事件如果不触发,大家就都得等待,而这个第一个是自动获取的。而如果在线程里去除ReleaseMutex,其它的线程竟然还能运行,仔细一想,发现可能是线程退出后Mutex内核资源被操作系统回收了,其它线程就可以使用了。

这个好办,做一个验证就OK了,在线程内增加了等待,getchar();不再释放,结果发现其它线程就全部都完蛋了。然后在等待前增加释放,然后程序又恢复了当初自动运行的状态,也就是说,线程不是全部运行了起来,是一个个线程运行完成了,逐次被系统回收资源后,又一个个获得Mutex,不断的重复,就好像全部的线程都被ReleaseMutex给唤醒了。

当然,还有CreateMutex(NULL, TRUE, NULL);第二参数为True,这个一定要小心,写测试程序时,就两个来回注释,一不小心没注意,认为自己的程序有误,还好及时发现了这个参数。

这个参数如果为TRUE就代表程序创建者自动获得了这个状态,如果它自己不释放,别人就只能等待了,所以后面的三个线程就全部不再运行了。差点又掉进陷阱。

这里还得顺便说明一个问题,使用OpenMutex(MUTEX_ALL_ACCESS, FALSE, _T("A"));时,这个返回的句柄的值可能与你创建的句柄的值不同。原来看书上说过,内核的句柄在底层其实是用一个指针实现的(不敢确定,因为时间太长了,书名也忘记了),所以你打开的句柄可能只是一个指针的拷贝,所以造成值得不同。

好多年,使用Mutex已经都是在RAII的状态下使用智能指针来控制,一些具体的细节都渐渐的淡忘了,不好好学习不行,不认真温习更是不行。

孔老二说得好:温故而知新。

 

 

 

  评论这张
 
阅读(329)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017