mutex互斥问题

dir541541 2009-08-11 10:11:49

UINT WINAPI Thread1(LPVOID para)
{
printf("Enten thread1\n");
HANDLE *phMutex = (HANDLE *)para;
// 得到互斥体
WaitForSingleObject(*phMutex, INFINITE);
// 对于同一个线程,主要获得互斥体,还可以获得多次
//WaitForSingleObject(*phMutex, INFINITE);
// 等待2s
Sleep(2*1000);
printf("Leave thread1\n");
// 释放
ReleaseMutex(*phMutex);
return 0;
}

UINT WINAPI Thread2(LPVOID para)
{
printf("Enten thread2\n");
HANDLE *phMutex = (HANDLE *)para;
// 得到互斥体
WaitForSingleObject(*phMutex, INFINITE);
// 等待2s
Sleep(2*1000);
printf("Leave thread2\n");
// 释放
ReleaseMutex(*phMutex);
return 0;
}

int main()
{
HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);
HANDLE hThread1 = (HANDLE)_beginthreadex(NULL, 0, Thread1, &hMutex, 0, NULL);
HANDLE hThread2 = (HANDLE)_beginthreadex(NULL, 0, Thread2, &hMutex, 0, NULL);
// 等待6s
Sleep(6*1000);

system("pause");
return 0;
}

结果为:
Enten thread1
Enten thread2
Leave thread1
Leave thread2
书上的例子。但结果和书上不一样。
书上为:
Enten thread1
Leave thread1
Enten thread2
Leave thread2

why?
...全文
121 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
dir541541 2009-08-12
  • 打赏
  • 举报
回复
明白了~多谢
wltg2001 2009-08-11
  • 打赏
  • 举报
回复
不过我有点不明白。Thread1创建之后就等待,还是一直等待状态。那他是等谁?执行WaitForSingleObject之后Thread1是挂起还是怎么了?从例子的输出来看他应该是继续执行后面的语句,等待2s之后输出。然后转去执行Thread2
====================
Thread1创建之后并不是等待,它执行了到了Sleep时才等待的,这时系统的线程调度才去调度线程二,线程二输出Enten thread2,然后执行WaitForSingleObject,由于线程一此时占用的互斥对象,所以WaitForSingleObject被阻塞了,等到线程一Sleep的时间到了,继续被调度到,执行到ReleaseMutex释放掉占用的互斥对象。线程一执行完了,由于此时线程二WaitForSingleObject等待的互斥对象被释放了,变成了有信号状态了,所以线程二被调度到,向下执行。
dronly 2009-08-11
  • 打赏
  • 举报
回复
WaitForSingleObject(*phMutex, INFINITE);
//代码
ReleaseMutex(*phMutex);

这两行之间是锁住的保护区,在保护区里面的代码对于线程来说是串行的,你两个printf都锁里面可肯定是书上的结果的。

但是如果把第一个printf放外面第二方printf方里面的话,只有第二个是串行的,如果你多运行几次的话又可能会出现
Enten thread2
Enten thread1
Leave thread1
Leave thread2
这样的结果的
jasonM2008 2009-08-11
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 jasonm2008 的回复:]
与你创建的互斥对象的类型相关,你是不是创建的是人工重置的互斥对象,你将其改为自动充值类型的对象再试一试?
[/Quote]
看错了,是事件对象才会我说出现的情况!
dir541541 2009-08-11
  • 打赏
  • 举报
回复
汗。原来printf的位置和书上不一样
书上是把printf放在WaitForSingleObject之后的,我是放在之前了
改过来就和例子一样了- -
不过我有点不明白。Thread1创建之后就等待,还是一直等待状态。那他是等谁?执行WaitForSingleObject之后Thread1是挂起还是怎么了?从例子的输出来看他应该是继续执行后面的语句,等待2s之后输出。然后转去执行Thread2
jasonM2008 2009-08-11
  • 打赏
  • 举报
回复
与你创建的互斥对象的类型相关,你是不是创建的是人工重置的互斥对象,你将其改为自动充值类型的对象再试一试?
wltg2001 2009-08-11
  • 打赏
  • 举报
回复
注意,hMutex是一个局部变量,从函数返回后,它的值就是随机的,你在线程里使用它的地址没有确定性,所以,你要把hMutex声明为全局变量就好了
============
在线程执行过程中,主函数又没退出,它的地址怎么没有确定性了?
dir541541 2009-08-11
  • 打赏
  • 举报
回复
改成全局的也不行。结果还是那样
wltg2001 2009-08-11
  • 打赏
  • 举报
回复
书上的结果错了吧,第一线程执行时输出Enten thread1,然后等待,此时线程二就会开始执行,输出Enten thread2,然后转放等待,等线程一转为就绪之后开始执行会输出Leave thread1,再然后。。。
实验的结果是正确的啊!
socoola 2009-08-11
  • 打赏
  • 举报
回复
HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);
HANDLE hThread1 = (HANDLE)_beginthreadex(NULL, 0, Thread1, &hMutex, 0, NULL);
HANDLE hThread2 = (HANDLE)_beginthreadex(NULL, 0, Thread2, &hMutex, 0, NULL);
注意,hMutex是一个局部变量,从函数返回后,它的值就是随机的,你在线程里使用它的地址没有确定性,所以,你要把hMutex声明为全局变量就好了
haipoliehu 2009-08-11
  • 打赏
  • 举报
回复
按照你现在的代码 得出现在的输出没有问题,书上的结果错了

15,471

社区成员

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

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