请教一个关于互斥对象的问题(createmutex)

helae 2008-04-15 10:52:44
程序如下:
#include <windows.h>
#include <iostream.h>

DWORD WINAPI Fun1Proc(
LPVOID lpParameter // thread data
);

DWORD WINAPI Fun2Proc(
LPVOID lpParameter // thread data
);

int index=0;
int tickets=100;
HANDLE hMutex;

void main()
{
HANDLE hThread1;
HANDLE hThread2;
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);

hMutex=CreateMutex(NULL,FALSE,NULL);

Sleep(4000);// Sleep(10);
}

DWORD WINAPI Fun1Proc(
LPVOID lpParameter // thread data
)
{

while(TRUE)
{
WaitForSingleObject(hMutex,INFINITE);
if(tickets>0)
{
Sleep(1);
cout<<"thread1 sell tickets : "<<tickets--<<endl;
}
else
break;
ReleaseMutex(hMutex);
}

return 0;
}

DWORD WINAPI Fun2Proc(
LPVOID lpParameter // thread data
)
{
while(TRUE)
{
WaitForSingleObject(hMutex,INFINITE);
if(tickets>0)
{
Sleep(1);
cout<<"thread2 sell tickets : "<<tickets--<<endl;
}
else
break;
ReleaseMutex(hMutex);
}

return 0;
}

我的疑惑是
线程1在释放了hMutex后,线程2就会马上获得hMutex吗?

该程序运行的结果是
thread1 sell tickets :100
thread2 sell tickets :99
thread1 sell tickets :98
thread2 sell tickets :978
....

但有没有可能出现如下的运行结果呢
thread1 sell tickets :60
thread1 sell tickets :59
thread2 sell tickets :58
thread1 sell tickets :57


...全文
110 点赞 收藏 10
写回复
10 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
rjabcd 2008-04-17
[Quote=引用 7 楼 helae 的回复:]
那有没有什么办法能保证线程1在ReleaseMutex后线程2一定能获得Mutex
[/Quote]
当然有办法可以解决:
把Thread转为Fiber,然后自己进行调度
回复
lyserver 2008-04-15
完全不是一回来,互斥量是用来同步多线程的(不仅仅是暂停),sleep只是让当前线程暂停一下。
回复
helae 2008-04-15
mutex互斥是不是等同于sleep呢
sleep是让线程暂停运行,ReleaseMutex也会让线程暂停运行呢
回复
unicode 2008-04-15
这就是mutex互斥呀
如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体
回复
helae 2008-04-15
CreateEvent
也能实现互斥?
能不能讲解一下CreateEvent的含义和用法啊
回复
gomoku 2008-04-15
好问题!
[Quote=引用 5 楼 helae 的回复:]
我主要想知道的是,在线程1 ReleaseMutex后,线程1有没有可能马上又获得Mutex?
[/Quote]

看看以下代码,你会发现mutex互斥本身并不能使你的线程的执行顺序化.


//加这一行Sleep到 Fun1Proc的同步体以外:

Sleep(10); // <-------add this line

WaitForSingleObject(hMutex,INFINITE);
if(tickets>0)
{
Sleep(1);
cout < <"thread1 sell tickets : " < <tickets-- < <endl;
}
else
{
break;
}
ReleaseMutex(hMutex);


这样子想想,如果有3个线程的等待同一个mutex,谁会得到呢? 答案是,目前我们不好确定, 微软说该种线程调度会是公平的,但具体的调度方法并没有公开(有利于微软以后更改调度算法). 目前的算法非常有可能是简单的FIFO(先到先服务), 所以你的示范程序看起来正好达到了顺序化的效果.

mutex一般是用来保护资源的, 它跟CriticalSection很像, 但它可以跨越进程使用而CriticalSection不能.
如果你的目的是顺序化执行,你可参考以下使用事件的代码:


#include <windows.h>
#include <iostream>
using namespace std;

int tickets=100;
HANDLE hSold;
HANDLE hProduced;

DWORD WINAPI FunProc( LPVOID lpParameter )
{
BOOL isSeller = (BOOL)lpParameter;
HANDLE hPrerequisite = isSeller ? hSold : hProduced;
HANDLE hSignaling = isSeller ? hProduced : hSold;

while(TRUE)
{
WaitForSingleObject(hPrerequisite,INFINITE);
if(tickets>0)
{
cout << "thread" << (isSeller ? "1 sell":"2 buy ") << " tickets : " << tickets-- << endl;
}
else
{
break;
}
SetEvent(hSignaling);
}
return 0;
}

void main()
{
hSold = CreateEvent(NULL, FALSE, TRUE, NULL);
hProduced = CreateEvent(NULL, FALSE, FALSE, NULL);

CloseHandle(CreateThread(NULL,0,FunProc,(LPVOID)TRUE ,0,0));
CloseHandle(CreateThread(NULL,0,FunProc,(LPVOID)FALSE,0,0));

getchar();
}



回复
helae 2008-04-15
那有没有什么办法能保证线程1在ReleaseMutex后线程2一定能获得Mutex
回复
rjabcd 2008-04-15
[Quote=引用 5 楼 helae 的回复:]
我主要想知道的是,在线程1 ReleaseMutex后,线程1有没有可能马上又获得Mutex?
[/Quote]

可以。因为你只是sleep(1),如果时间超过20毫秒,那基本没有可能。
回复
helae 2008-04-15
我主要想知道的是,在线程1 ReleaseMutex后,线程1有没有可能马上又获得Mutex?
回复
scq2099yt 2008-04-15
仔细看看孙鑫的教程,上面讲得很详细
回复
相关推荐
发帖
VC/MFC
创建于2007-09-28

1.5w+

社区成员

VC/MFC相关问题讨论
申请成为版主
帖子事件
创建了帖子
2008-04-15 10:52
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……