关于使用EVENT同步线程的一个问题,谢谢!!

RabbitLBJ 2010-07-26 09:45:21
先上代码

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

HANDLE h;

ULONG WINAPI f1(LPVOID param)
{

for(int i=0;i<100;i++)
{
int rev=::WaitForSingleObject(h,INFINITE);
if(rev==WAIT_OBJECT_0)
{
// ResetEvent(h);
cout<<"the thread1 is:"<<i<<endl;
SetEvent(h);
}
}
return 0;
}


ULONG WINAPI f2(LPVOID param)
{

for(int i=0;i<100;i++)
{
int rev=::WaitForSingleObject(h,INFINITE);
if(rev==WAIT_OBJECT_0)
{
// ResetEvent(h);
cout<<"the thread2 is:"<<i<<endl;
SetEvent(h);
}
}
return 0;
}

int main(int argc, char* argv[])
{
DWORD id1,id2;
h=CreateEvent(NULL,FALSE,TRUE,"WANGXU");
CreateThread(NULL,0,f1,NULL,0,&id1);
CreateThread(NULL,0,f2,NULL,0,&id2);

Sleep(5000);
return 0;
}


想一下为什么我把主函数中创建的事件设置成手动重置信号,然后将注释F1,F2中RESET的注释删除,对象还是同步不了。
...全文
123 18 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
wltg2001 2010-07-26
  • 打赏
  • 举报
回复
改成这样吧:
#include <windows.h>
#include <iostream>
using namespace std;

HANDLE h;

ULONG WINAPI f1(LPVOID param)
{
int rev=::WaitForSingleObject(h,INFINITE);
for(int i=0;i<100;i++)
{

// ResetEvent(h);
cout<<"the thread1 is:"<<i<<endl;

}
SetEvent(h);
return 0;
}


ULONG WINAPI f2(LPVOID param)
{
int rev=::WaitForSingleObject(h,INFINITE);
for(int i=0;i<100;i++)
{
// ResetEvent(h);
cout<<"the thread2 is:"<<i<<endl;

}
SetEvent(h);
return 0;
}

int main(int argc, char* argv[])
{
DWORD id1,id2;
h=CreateEvent(NULL,FALSE,TRUE,"WANGXU");
CreateThread(NULL,0,f1,NULL,0,&id1);
CreateThread(NULL,0,f2,NULL,0,&id2);

Sleep(5000);
return 0;
}
adamwyb 2010-07-26
  • 打赏
  • 举报
回复
首先,我觉得不应该去除Reset,不然你wait的事件一直处于有信号状态,那么WaitForSingleObject就不会阻塞。其次,你放入Reset仍不能同步,是这样的一个情况:
假设第一个线程等到了事件,那么就跳入了if语句中,假设这个时候,时间片刚好结束,那么第二个线程的WaitForSingleObject仍然可以返回。这个时候,就不会保证cout安全了。
解决办法,现在觉得还是用Mutex吧,因为这个函数是将等待和置位统一执行的。
RabbitLBJ 2010-07-26
  • 打赏
  • 举报
回复
没人了??
hellboy198502 2010-07-26
  • 打赏
  • 举报
回复

h=CreateEvent(NULL,FALSE,TRUE,"WANGXU");

改为

h=CreateEvent(NULL,FALSE,FALSE,"WANGXU");
RabbitLBJ 2010-07-26
  • 打赏
  • 举报
回复
刚刚试了下使用两个事件,但是同步没对,应该是我弄错了,还请楼上的朋友再仔细说一说!
我觉得使用一个事件应该也不算很麻烦吧,我是模仿临界区那样实现的。
nbabest23 2010-07-26
  • 打赏
  • 举报
回复
两个线程都是用同一个事件 一会开一会关的 ,很难准确的判断到底是那个线程获得了又信号状态
为什么不使用两个事件呢,一个输出完了 在打开另一个
RabbitLBJ 2010-07-26
  • 打赏
  • 举报
回复
就是两个函数完整输出各自的字符串啊,如果不同步的话输出的字符串就是夹杂在一起的!!
adamwyb 2010-07-26
  • 打赏
  • 举报
回复
[Quote=引用楼主 rabbitlbj 的回复:]
想一下为什么我把主函数中创建的事件设置成手动重置信号,然后将注释F1,F2中RESET的注释删除,对象还是同步不了。[/Quote]

你想要的同步是怎样的流程?
RabbitLBJ 2010-07-26
  • 打赏
  • 举报
回复
呵呵,谢谢楼上的朋友了!
adamwyb 2010-07-26
  • 打赏
  • 举报
回复
上面有个笔误:

你如果想测试单核,可以在程序开头放一个getchar(),...


adamwyb 2010-07-26
  • 打赏
  • 举报
回复
我突然想到了个原因,因为你的机器是双核的。所以两个CPU运行当然就会交替了。你如果想测试单线程,可以在程序开头放一个getchar(),作为暂停下。当程序启动后,你打开任务管理器,在进程标签里,找到你的执行文件,然后点右键-关系设置,这个时候如果你的CPU0与CPU1前面的都有勾的话,那肯定就是双核CPU啦。然后勾掉一个,保存一个。这个时候在你程序里回车,运行程序。我觉得你就能看到你想要的结果了。
RabbitLBJ 2010-07-26
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 adamwyb 的回复:]
引用 11 楼 wltg2001 的回复:
引用 10 楼 rabbitlbj 的回复:
我也不明白放在外面有什么区别,::WaitForSingleObject(h,INFINITE);反正不是一直挂在那里的吗??

当然有区别了,比如你的代码中的 SetEvent(h);放在for的里面,第一次cout之后,SetEvent就会被调用,此时h处于有信息状态,但是线程调度时,可以你的线程……
[/Quote]

呵呵,我就是这样想的,并不是要等一个FOR循环完之后再进入另一个FOR循环,只是要两个循环夹杂输出(但要同步,每次输出一条完整的信息,不然输出的字符串就是乱的)。但是我用临界区和事件查看结果,输出都是交替的,我改变线程的优先级也不行,是哪里出问题了呢??
至善者善之敌 2010-07-26
  • 打赏
  • 举报
回复
想让楼主说明一下,他写这段代码的用途
adamwyb 2010-07-26
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 wltg2001 的回复:]
引用 10 楼 rabbitlbj 的回复:
我也不明白放在外面有什么区别,::WaitForSingleObject(h,INFINITE);反正不是一直挂在那里的吗??

当然有区别了,比如你的代码中的 SetEvent(h);放在for的里面,第一次cout之后,SetEvent就会被调用,此时h处于有信息状态,但是线程调度时,可以你的线程一失去了CPU时间,线程二被调度,此时h有信号……
[/Quote]

我理解楼主的意思是,他并不要将线程1运行完后再运行线程2,而是保证两个线程“cout输出的字符串不要夹杂在一起”。我理解的是否正确?
wltg2001 2010-07-26
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 rabbitlbj 的回复:]
我也不明白放在外面有什么区别,::WaitForSingleObject(h,INFINITE);反正不是一直挂在那里的吗??
[/Quote]
当然有区别了,比如你的代码中的 SetEvent(h);放在for的里面,第一次cout之后,SetEvent就会被调用,此时h处于有信息状态,但是线程调度时,可以你的线程一失去了CPU时间,线程二被调度,此时h有信号那么线程就可以执行从而cout数据,然后线程二在for里面又SetEvent(h),此时h又是有信号的,线程二可能会失去CPU时间,线程一被调度,这样线程一又可以cout了,这就产生了线程一与线程二交替输出的现象了。
将WaitForSingleObject和SetEvent放在for外面,只有for循环完全之后,h才会有信号,即使当线程一失去CPU时间,线程二被调度,由于h无信号,所以线程在WaitForSingleObject处阻塞,只有当线程一的for循环结束后SetEvent被调用,线程二才可以继续下去。
RabbitLBJ 2010-07-26
  • 打赏
  • 举报
回复
我也不明白放在外面有什么区别,::WaitForSingleObject(h,INFINITE);反正不是一直挂在那里的吗??
adamwyb 2010-07-26
  • 打赏
  • 举报
回复
不好意思,看来我对WaitForSingleObject还是了解不透啊。收回刚才的解释,希望不要误导楼主。但我不太明白为什么放到for循环外和放到内部有什么区别?
Eleven 2010-07-26
  • 打赏
  • 举报
回复
把你的WaitForSingleObject/SetEvent移动到for语句之上即可,类似这样
ULONG WINAPI f2(LPVOID param)
{
int rev=::WaitForSingleObject(h,INFINITE);
for(int i=0;i<100;i++)
{

if(rev==WAIT_OBJECT_0)
{
// ResetEvent(h);
cout<<"the thread2 is:"<<i<<endl;

}
}
SetEvent(h);
return 0;
}

15,473

社区成员

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

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