【问题标题】:Why semaphore is released but WaitForSingleObject() still stuck?为什么释放信号量但 WaitForSingleObject() 仍然卡住?
【发布时间】:2015-05-14 11:15:11
【问题描述】:

更新:我发现他们释放的信号量不是监控线程正在等待的信号量!我用cout<<ready发现线程正在释放的信号量是00000394,这不是监视器线程正在等待的信号量的句柄。这个问题的可能原因是什么?谢谢!


我是 Windows 中多线程编程的新手。今天,当我编写我的在线游戏服务器时,我尝试在 Windows 中使用信号量。它是基于 IOCP 编写的,因此每条消息都在单独的线程中处理。一场比赛由 4 名玩家组成。

我期望它做的是:收到消息时,一个新线程启动并释放ready。有一个监听线程等待4个ready,然后释放4个all_ready。每个线程等待一个all_ready 并继续。

代码在这里:

CGameHost 是 4 人游戏的经理。

CGameHost::CGameHost(void)
{
    init_times=0;
    ready = CreateSemaphore(NULL, 0, 4, NULL);
    read = CreateSemaphore(NULL, 0, 4, NULL);
    all_ready = CreateSemaphore(NULL, 0, 4, NULL);
    all_read = CreateSemaphore(NULL, 0, 4, NULL);
    monitor_thread = (HANDLE)_beginthreadex(NULL, 0, Monitor, (LPVOID)this, NULL, 0);
}

unsigned __stdcall CGameHost::Monitor( LPVOID p ) // a static function
{
    CGameHost *nowp = (CGameHost *)p;
    while(true)
    {
        int i;
        for(i=1;i<=MAX_PLAYER;i++)
        {
            WaitForSingleObject(nowp->ready, INFINITE);//stuck here
            cout<<"Get Ready!"<<endl; // This is not outputed, which means it stucks in the last row.
        }

        for(i=1;i<=MAX_PLAYER;i++)
        {
            ReleaseSemaphore(nowp->all_ready, 1, NULL);
        }

        for(i=1; i<=MAX_PLAYER; i++)
        {
            WaitForSingleObject(nowp->read, INFINITE);
        }

        for(i=1; i<=MAX_PLAYER;i++)
        {
            ReleaseSemaphore(nowp->all_read, 1, NULL);
        }
    }
    return 0;
}

void CGameHost::ReleaseReady()
{
    ReleaseSemaphore(ready, 1, NULL);
}

void CGameHost::WaitAllReady()
{
    WaitForSingleObject(all_ready, INFINITE);
}

void CGameHost::ReleaseRead()
{
    ReleaseSemaphore(read, 1, NULL);
}

void CGameHost::WaitAllRead()
{
    WaitForSingleObject(all_read, INFINITE);
}

DataProcess::Game 是传入游戏消息的消息处理程序。

CMessage Dataprocess::Game( CMessage* recv_msg )
{
    CMessage ret;
    int now_roomnum = recv_msg->para1;
    int now_playernum = recv_msg->para2;
    if(true)
    {
        cout<<"Received Game Message: "<<endl;
        cout<<"type2 = "<<recv_msg->type2;
        cout<<" player_num = "<<now_playernum<<" msg= "<<recv_msg->msg<<endl;
    }

    if(recv_msg->type2 == MSG_GAME_OPERATION)
    {
        ret.type1 = MSG_GAME;
        ret.type2 = MSG_GAME_OPERATION;

        cout<<"Entered from "<<now_playernum<<endl;

        game_host[now_roomnum].SetMessage(now_playernum, recv_msg->msg);
        game_host[now_roomnum].ReleaseReady();

        cout<<"Released Ready from "<<now_playernum<<endl;//this is shown

        game_host[now_roomnum].WaitAllReady();//stuck here

        cout<<"AllReady from"<<now_playernum<<endl;//not shown

    }
    return ret;
}

您的回复对像我这样的Windows多线程程序员初学者会有很大帮助!谢谢!

【问题讨论】:

  • 你可能想要的是使用 WaitForMultipleObjects
  • 嗯... IOCP 并不意味着每条消息都在单独的线程上处理。也许您也应该包含您的 IOCP 代码?
  • 在我看来,您正在使您的消息处理程序陷入僵局。一旦第一个玩家准备好,就无法处理更多消息。你必须重新考虑这一点。
  • @Luaan 说实话,IOCP部分不是我写的……所以不知道该发什么部分……
  • @HansPassant 但是如果第一个玩家准备好了,监控线程应该捕获ready 并显示“准备好!”而我根本没有看到这条消息。

标签: c++ windows multithreading semaphore


【解决方案1】:

如果我了解您的需求,您可能应该有这样的东西..

处理 hPlayersReady[4]; 处理 hAllPlayed;

创建这 5 个事件,然后在你的监控线程上, 做这样的事情......

while(true)
{
// Wait for all players to move
WaitForMultipleObjects(4, &hPlayersReady, true, INFINITE);
// Process move
...
// Advise players the move was processed...
SetEvent(hAllPlayed);
}

在你的播放器线程 X 上

while(true)
{
// Make my move
...
// Advise monitor I'm ready
SetEvent(hPlayersReady[X]);
// Wait for ready to do another move
WaitForSingleObject(hAllPlayed);
}

【讨论】:

  • 谢谢你的回复,不过我觉得不会有用,因为hAllPlayed要连读4次,不知是不是只能读一次...跨度>
  • 看来你得解释信号量和事件之间的区别了。
  • @DarkZero,我没听懂你的评论,你说的“必须服用 4 次”是什么意思?
  • 在这个游戏中,每帧会有四个玩家将他们的动作发布到服务器,因此有四个线程存储他们的动作并请求所有动作。比如玩家 1 会告诉服务器他的动作,他会询问所有玩家的动作,玩家 2 3 4 也是如此,所以每个人都会等待 hAllPlayed 继续,因此等待了 4 次。
  • @DarkZero,必须使用“手动重置”创建 hAllPlayed,然后您需要从线程触发“确认”响应,以便监控线程执行重置。
【解决方案2】:

嗯,我自己解决了。原因是我在创建线程后再次使用CreateSemaphore,让玩家线程访问不同的信号量作为监控线程......对不起我的愚蠢,谢谢你告诉我这么多!

【讨论】:

    猜你喜欢
    • 2013-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-26
    • 2011-06-16
    • 2021-12-28
    相关资源
    最近更新 更多