我以name创建的Mutex对象,在CloseHandle后仍然可以OpenMutex,为什么啊?

darkread 2017-01-18 05:11:29
五个按钮
CString name = _T("DRRR_TEST_MUTEX");

按钮1 创建:
 CreateMutex(NULL, FALSE,  name);

按钮2: 锁定:
hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, name);
WaitForSingleObject(hMutex, 0L);

按钮3 释放:
hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, name);
ReleaseMutex(hMutex, 0L);

按钮4 关闭:
hMutex=OpenMutex(MUTEX_ALL_ACCESS, FALSE, name);
CloseHandle(hMutex);

按钮5 线程执行锁定和释放:
//起一个线程,在线程中执行下面代码
hMutex=OpenMutex(MUTEX_ALL_ACCESS, FALSE, name);
WaitForSingleObject(hMutex, 0L);
ReleaseMutex(hMutex, 0L);

测试1:按照 [创建] [锁定] [释放] [关闭] 顺序点击成功。再点按钮2,仍然提示成功。
测试2:按照 [创建] [锁定] [释放] [关闭] [线程执行锁定和释放] 顺序点击,1 2 3 4 2 成功,5提示进入临界区失败,等待超时。
测试3:按照 [创建] [锁定] [释放] [关闭] [锁定] [释放] [线程执行锁定和释放] 顺序点击,均成功。
测试4:按照只点击 [锁定] ,失败,提示OpenMutex失败。
上述测试均在重启测试程序后进行。
我的疑惑在于,如果CloseHandle后,不论是主线程还是子线程都可以再次OpenMutex,那么CloseHandle有什么用处?

第二组实验
该程序同时启动两个进程 P1和P2
P1-[创建] 表示 P1程序点击按钮1[创建]

测试1:P1-[锁定] 提示 OpenMutex失败。注释:证明该对象不创建是不存在的。
测试2:P1-[创建] P2-[锁定] P2-[线程执行锁定和释放],在P2-[线程执行锁定和释放]提示进入锁定临界区失败,WAIT_TIMEOUT。注释:证明可以跨进程使用。
测试3:P1-[创建] P2-[锁定] P2-[释放] P2-[线程执行锁定和释放],成功。
测试4:P1-[创建] P1-[锁定] P1-[释放] P2-[线程执行锁定和释放],成功。
测试5:P1-[创建] P1-[锁定] P2-[释放] P2-[线程执行锁定和释放],P2-[释放]提示释放失败,P2-[线程执行锁定和释放]提示进入锁定临界区失败,WAIT_TIMEOUT。
注释:测试3 4 5 证明锁定和释放必须在一个线程中完成,否则无效。
测试6:P1-[创建] P1-[锁定] P1-[释放] P1-[关闭] P2-[线程执行锁定和释放],成功。注释:此处为疑惑 P1-[关闭]后仍然P2可以OpenMutex进行操作。于是又了测试7
测试7:P1-[创建] P1-[锁定] P1-[释放] P1-[关闭] P1进程退出 P2-[线程执行锁定和释放],P2-[线程执行锁定和释放]提示OpenMutex失败。
测试8:P1-[创建] P1退出 P2-[锁定],P2-[锁定]提示对象不存在

第三组实验:
新增一个按钮,同为两个进程P1 P2
按钮6 线程执行创建、锁定、释放、关闭、等待10秒退出
测试1:P1-[线程执行创建、锁定、释放、关闭、等待10秒退出],成功。注释:这是基准。
测试2:P1-[线程执行创建、锁定、释放、关闭、等待10秒退出] P2-[锁定],P2-[锁定]提示Mutex不存在。注释:猜测Mutex是否需要等待线程退出后销毁,因此考虑
测试3:P1-[线程执行创建、锁定、释放、关闭、等待10秒退出] 在P1等待10秒时按下P2-[锁定] P2-[线程执行锁定和释放],成功。注释:猜猜Mutex对象由哪个线程创建,那么只要线程不退出那么必然可以被其它线程OpenMutex也就是说该对象未销毁。

第四组实验:
修改之前的过程,把OpenMutex()第二个参数 BOOL bInheritHandle改成 True,测试结果和之前一致

第五组实验:
修改之前的过程,把CreateMutex()第二个参数 BOOL bInitialOwner改成 TRUE,作用就是创建即锁定,与是否销毁对象无关。

由此可见,只要[创建]执行线程退出,则对象销毁是否CloseHandle无关。

结论,CloseHandle不能关闭对象,只有在创建或者打开Mutex对象的全部线程退出后该对象才销毁。
但是MSDN上下面这段话如何理解?
Use the CloseHandle function to close the handle. // 用CloseHandle来关闭句柄
The system closes the handle automatically when the process terminates. // (操作)系统在进程终止后自动关闭句柄
The mutex object is destroyed when its last handle has been closed. // mutex对象在它的最后一个句柄关闭时被销毁
第二句已经被证明是对的。
但是联合起来看第一句和第三句。用CloseHandle可以关闭句柄,并且在最后一个句柄被关闭后mutex被销毁。看第二组实验 测试6,到P1-[关闭]后为什么P2-[线程执行锁定和释放]仍然可以打开该Mutex对象?
...全文
219 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
darkread 2017-01-19
  • 打赏
  • 举报
回复
引用 1 楼 cutmelon 的回复:
我没看大段的文字,就看了下代码,初步估计你对内核对象的创建、句柄打开、句柄关闭,对象删除这几个概念理解有误,你在每次Open之后都Close一下再检查你的实验过程,然后好好看看MSDN的解释吧
你说的对。我的想法有问题的。实际上每次打开后,不CloseHandle,那么Open的时候Handle值是会变的。想法有问题。如果一次性创建锁定释放关闭,那么再次OpenMutex是提示对象不存在。
oyljerry 2017-01-18
  • 打赏
  • 举报
回复
系统回收mutex可能有时间差。然后就是确认你的句柄是否引用的都关闭了
schlafenhamster 2017-01-18
  • 打赏
  • 举报
回复
CloseHandle The CloseHandle function closes an open object handle.
cutmelon 2017-01-18
  • 打赏
  • 举报
回复
我没看大段的文字,就看了下代码,初步估计你对内核对象的创建、句柄打开、句柄关闭,对象删除这几个概念理解有误,你在每次Open之后都Close一下再检查你的实验过程,然后好好看看MSDN的解释吧

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧