为什么信号量被释放但 WaitForSingleObject() 仍然卡住?
Why semaphore is released but WaitForSingleObject() still stuck?
更新:我发现他们正在释放的信号量不是监视线程正在等待的信号量!我使用 cout<<ready
发现线程正在释放的信号量是 00000394
,这不是监视线程正在等待的信号量的句柄。这个问题的可能原因是什么?谢谢!
我是 Windows 的多线程编程新手。今天在写我的在线游戏服务器时,我尝试在Windows中使用信号量。它基于 IOCP 编写,因此每条消息都在单独的线程中处理。一场比赛由 4 名玩家组成。
我期望它做的是:当收到一条消息时,一个新的线程启动并释放一个ready
。有个监听线程等待4ready
,然后释放4all_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多线程程序员初学者有很大的帮助!谢谢!
如果我了解您的需求,您可能应该有这样的东西..
处理 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);
}
嗯,我自己解决了。原因是我在创建线程后又使用了CreateSemaphore
,让播放器线程访问不同的信号量作为监听线程...对不起我的愚蠢,谢谢你告诉我这么多!
更新:我发现他们正在释放的信号量不是监视线程正在等待的信号量!我使用 cout<<ready
发现线程正在释放的信号量是 00000394
,这不是监视线程正在等待的信号量的句柄。这个问题的可能原因是什么?谢谢!
我是 Windows 的多线程编程新手。今天在写我的在线游戏服务器时,我尝试在Windows中使用信号量。它基于 IOCP 编写,因此每条消息都在单独的线程中处理。一场比赛由 4 名玩家组成。
我期望它做的是:当收到一条消息时,一个新的线程启动并释放一个ready
。有个监听线程等待4ready
,然后释放4all_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多线程程序员初学者有很大的帮助!谢谢!
如果我了解您的需求,您可能应该有这样的东西..
处理 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);
}
嗯,我自己解决了。原因是我在创建线程后又使用了CreateSemaphore
,让播放器线程访问不同的信号量作为监听线程...对不起我的愚蠢,谢谢你告诉我这么多!