[严肃]ReleaseMutex的疑问

心中那自由的世界 架构师  2008-04-29 05:31:00

MSDN中关于ReleaseMutex函数有这样一句话:

Remarks
The ReleaseMutex function fails if the calling thread does not own the mutex object.

如果调用ReleaseMutex的线程对mutex没有拥有权的话,函数调用将失败.
那么什么情况下能够拥有mutex的所有权呢,下面说调用wait 函数和创建mutex即可,调用ReleaseMutex是释放所有权.

我的问题就这样产生了....




//-------------------------------demo.h----------------------------------------------

class CDemo
{
public:
CDemo(void);
~CDemo(void);
void Lock();
void UnLock();
private:
HANDLE m_hread;
};

//-------------------------------demo.cpp----------------------------------------------

#include "StdAfx.h"
#include "Demo.h"

CDemo::CDemo(void)
:m_nread(0)
{
m_hread = CreateMutex(NULL, FALSE, NULL);
}

CDemo::~CDemo(void)
{
CloseHandle(m_hread);
}

void CDemo::Lock(DWORD n)
{
WaitForSingleObject(m_hread, INFINITE);
AfxTrace(TEXT("LOCK %d\r\n"), ::GetCurrentThreadId());
}

void CDemo::UnLock(DWORD n)
{
AfxTrace(TEXT("Release %d\r\n"), ::GetCurrentThreadId());
if (!ReleaseMutex(m_hread))
{
TRACE("FAILED TO RELEASE\r\n");
}
}

//-------------------------------test.cpp---------------------------------------------

static UINT WINAPI LockThread(void *);
static UINT WINAPI UnLockThread(void *);

UINT CTest::LockThread(void *p)
{
CDemo *pP = static_cast<CDemo*>(p);
pP->Lock();
}

UINT CTest::UnLockThread(void *p)
{
CDemo* pP = static_cast<CDemo*>(p);
pP->UnLock();
}

CTest::OnBnTest()
{
const int THREAD_COUNT;
HANDLE hThreads[THREAD_COUNT + 1];

//...

HANDLE hThread1 = (HANDLE)_beginthreadex(NULL, 0, &LockThread, &demo, 0, NULL);
HANDLE hThread2 = (HANDLE)_beginthreadex(NULL, 0, &UnLockThread, &demo, 0, NULL);

}






函数执行没有,OUTPUT栏中没有找到 FAILED TO RELEASE, 这说明释放成功了,为什么?????是MSDN上面说的不对?如果它是对的,为什么这个地方可以释放成功?锁和解锁分别属于不同的线程啊.
...全文
830 点赞 收藏 12
写回复
12 条回复
cmkyec 2009年08月14日
mark
回复 点赞
心中那自由的世界 2008年04月30日
我不是要弄出RELEASE FAILED, 我是要搞清楚为什么没有拥有mutex的线程调用ReleaseMutex为什么不会失败!!!!

刚才回贴漏了一个字.
回复 点赞
心中那自由的世界 2008年04月30日
楼上的,我对你无语了,你调换了线程的执行次序,让UnLock先执行,这当然会失败了.开始我是没有认真看,现在我是认真看而且还执行了你的代码.我想的是Lock在前,UnLock在后,你竟然把顺序给我反过来了.

我不是要弄出RELEASE FAILED, 我是要搞清楚为什么没有拥有mutex的线程调用ReleaseMutex为什么会失败!!!!
谢谢你的回贴,虽然你没有搞懂我发贴的本意.
回复 点赞
knowledge_Is_Life 2008年04月30日
什么呀
回复 点赞
wesom 2008年04月30日
我昨晚已经测试过,记得用控制台选项编译(/subsystem:console),you can try again.
回复 点赞
心中那自由的世界 2008年04月30日
我没有把代码贴完整,你说的那个主线程退出子线程没有运行对我来说并不存在.

你的代码测试过吗?确实能打印出 FAILED TO RELEASE 来吗?

我在XP SP2 + VS2005没有这个输出.
回复 点赞
wesom 2008年04月30日
我估计你的问题是case 1,但是case 3你也要考虑,至少你的代码没有反映出来
回复 点赞
wesom 2008年04月30日
我想道理是一样的
case 1:
Thread1线程执行完毕后,该线程终止运行,系统将自动将互斥对象的ID置为0,该Mutex为signaled状态
Thread1执行完毕后,Thread2执行,ReleaseMutex返回成功
case 2:
Thread1线程执行未结束时,Thread2开始执行,ReleaseMutex返回必然是失败

之所以让Thread2先运行,是为了测试Thread2在Thread1 wait之前通过ReleaseMutex来调用nonsignaled状态的内核对象,返回也是失败
不知道我说的是否清楚?
回复 点赞
wesom 2008年04月29日
即如果线程2先执行必打印出你要的结果,哈哈
回复 点赞
wesom 2008年04月29日
你这里有2个问题:
1. 主线程退出后,2个子线程还没来的及运行就退出
2. m_hread = CreateMutex(NULL, FALSE, NULL); //互斥对象开始时不发出通知信号
wait func是指有线程对该内核对象请求资源后(如WaitForSingleObject、SignalObjectAndWait等详见csdn),该内核对象的状态由未通知状态nonsignaled置为已通知状态signaled
我改了下你的代码,如下,可提示出“FAILED TO RELEASE"


//-------------------------------demo.h----------------------------------------------

#include <windows.h>
#include <stdio.h>

class CDemo
{
public:
CDemo(void);
~CDemo(void);
void Lock();
void UnLock();
private:
HANDLE m_hread;
};

CDemo::CDemo(void)
:m_hread(0)
{
m_hread = CreateMutex(NULL, FALSE, NULL);
}

CDemo::~CDemo(void)
{
CloseHandle(m_hread);
}

void CDemo::Lock()
{
WaitForSingleObject(m_hread, INFINITE);
printf(TEXT("LOCK %d\r\n"), ::GetCurrentThreadId());
}

void CDemo::UnLock()
{
printf(TEXT("Release %d\r\n"), ::GetCurrentThreadId());
if (!ReleaseMutex(m_hread))
{
printf("FAILED TO RELEASE\r\n");
}
}

//-------------------------------console.cpp----------------------------------------------
#include <windows.h>
#include <process.h>
#include "deamon.h"

HANDLE g_Event;

UINT WINAPI LockThread(PVOID pvParam)
{
WaitForSingleObject(g_Event,INFINITE);
CDemo *pP = static_cast<CDemo*>(pvParam);
pP->Lock();
return 0;
}

UINT WINAPI UnLockThread(PVOID pvParam)
{
WaitForSingleObject(g_Event,INFINITE);
CDemo* pP = static_cast<CDemo*>(pvParam);
pP->UnLock();
return 0;
}

int main(int argc , char* argv[] )
{
HANDLE hThread[2];
CDemo demo;
//...
g_Event = CreateEvent(NULL,TRUE,FALSE,NULL);
DWORD dwThreadID;
hThread[1] = (HANDLE)_beginthreadex(NULL, 0, UnLockThread, &demo, 0, (unsigned *)&dwThreadID);
SetEvent(g_Event);
WaitForSingleObject(hThread[1],INFINITE);
hThread[0] = (HANDLE)_beginthreadex(NULL, 0, LockThread, &demo, 0, (unsigned *)&dwThreadID);

WaitForMultipleObjects(2, hThread, TRUE, INFINITE);
CloseHandle(hThread[0]);
CloseHandle(hThread[1]);
CloseHandle(g_Event);
getchar();
return 0;
}


回复 点赞
心中那自由的世界 2008年04月29日
是相同的,对同一个object做操作的.
回复 点赞
xfinal2006 2008年04月29日
LockThread()和UnLockThread()里面的pP是不同的吧,m_hread不是static,这样就是两个线程拥有两个不同的mutex了
回复 点赞
发动态
发帖子
进程/线程/DLL
创建于2007-09-28

6376

社区成员

4.9w+

社区内容

VC/MFC 进程/线程/DLL
社区公告
暂无公告