先上代码#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的注释删除,对象还是同步不了。

解决方案 »

  1.   

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

  2.   

    改成这样吧:
    #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;
    }
      

  3.   

    把你的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;
    }
      

  4.   

    不好意思,看来我对WaitForSingleObject还是了解不透啊。收回刚才的解释,希望不要误导楼主。但我不太明白为什么放到for循环外和放到内部有什么区别?
      

  5.   

    我也不明白放在外面有什么区别,::WaitForSingleObject(h,INFINITE);反正不是一直挂在那里的吗??
      

  6.   

    当然有区别了,比如你的代码中的 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被调用,线程二才可以继续下去。
      

  7.   


    我理解楼主的意思是,他并不要将线程1运行完后再运行线程2,而是保证两个线程“cout输出的字符串不要夹杂在一起”。我理解的是否正确?
      

  8.   


    呵呵,我就是这样想的,并不是要等一个FOR循环完之后再进入另一个FOR循环,只是要两个循环夹杂输出(但要同步,每次输出一条完整的信息,不然输出的字符串就是乱的)。但是我用临界区和事件查看结果,输出都是交替的,我改变线程的优先级也不行,是哪里出问题了呢??
      

  9.   

    我突然想到了个原因,因为你的机器是双核的。所以两个CPU运行当然就会交替了。你如果想测试单线程,可以在程序开头放一个getchar(),作为暂停下。当程序启动后,你打开任务管理器,在进程标签里,找到你的执行文件,然后点右键-关系设置,这个时候如果你的CPU0与CPU1前面的都有勾的话,那肯定就是双核CPU啦。然后勾掉一个,保存一个。这个时候在你程序里回车,运行程序。我觉得你就能看到你想要的结果了。
      

  10.   

    上面有个笔误:你如果想测试单核,可以在程序开头放一个getchar(),...
      

  11.   


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