C++ C++;游戏:pthread_cond_信号不';不要叫醒对手
我在做一个游戏,让用户和电脑玩。当轮到玩家时,电脑对手会考虑下一步行动。如果玩家移动到计算机对手计划移动的位置,计算机对手将再次开始搜索其移动 以下是主要功能和对手功能的概述: [更新]C++ C++;游戏:pthread_cond_信号不';不要叫醒对手,c++,pthreads,mutex,wait,C++,Pthreads,Mutex,Wait,我在做一个游戏,让用户和电脑玩。当轮到玩家时,电脑对手会考虑下一步行动。如果玩家移动到计算机对手计划移动的位置,计算机对手将再次开始搜索其移动 以下是主要功能和对手功能的概述: [更新] pthread_mutex_t mutex; pthread_cond_t cond; int main() { // ... initialize game variables, args to pass to opponent ... pthread_t thread; pthr
pthread_mutex_t mutex;
pthread_cond_t cond;
int main() {
// ... initialize game variables, args to pass to opponent ...
pthread_t thread;
pthread_create(&thread, NULL, opponent, &args);
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
while(!isGameOver()) {
pthread_mutex_lock(&mutex);
if(getCurrentPlayer() != PLAYER) {
pthread_cond_wait(&cond, &mutex);
}
if(getCurrentPlayer() == PLAYER) {
// ... update board with player's move ...
setCurrentPlayer(OPPONENT);
pthread_cond_signal(&cond);
}
pthread_mutex_unlock(&mutex);
}
}
void * opponent(void * args) {
// initialize move to something invalid
while(!isGameOver()) {
if(!isValid(move)) {
move = findMove();
}
pthread_mutex_lock(&mutex);
if(getCurrentPlayer() != OPPONENT) {
pthread_cond_wait(&cond, &mutex);
}
if(getCurrentPlayer() == OPPONENT) {
if(isValid(move)) {
// ... update board with opponent's move ...
setCurrentPlayer(PLAYER);
pthread_cond_signal(&cond);
}
}
pthread_mutex_unlock(&mutex);
}
}
目前,情况似乎就是这样:[更新]
- 对手找到了他的移动(findMove)
- 对手锁定互斥锁(pthread\u mutex\u lock)
- 对手开始等待(pthread_cond_wait)
- 主函数锁定互斥锁(pthread\u mutex\u lock)
- 球员开始行动
- 主线程表示该轮到对手了(pthread_cond_signal)
- 对手找到了他的移动(findMove)
- 对手开始等待(pthread_cond_wait)
- 球员开始行动
- 主线程表示该轮到对手了(pthread_cond_signal)
- 对手停止等待
- 对手做出了之前考虑过的动作
- 对手切换当前玩家(setCurrentPlayer)
- 重复
我对线程没有太多的经验,所以有人能帮我解决这里发生的事情吗,以及我如何修复它?我不知道我的互斥锁/解锁、条件信号/等待和setCurrentPlayer函数是否在正确的位置。当调用
pthread\u cond\u wait
时,互斥锁应该被锁定-该函数自动解锁互斥锁,等待信号,然后在返回前重新锁定互斥锁。互斥锁的目的是串行访问共享状态(在本例中为当前播放器),因此它应该在访问该共享状态时被锁定。循环应该更像:
while(!isGameOver()) {
if(!isValid(move)) {
move = findMove();
}
pthread_mutex_lock(&mutex); // LOCK HERE
if(getCurrentPlayer() != OPPONENT) {
pthread_cond_wait(&cond, &mutex);
}
if(getCurrentPlayer() == OPPONENT) {
if(isValid(move)) {
// NOT HERE pthread_mutex_lock(&mutex);
// ... update board with opponent's move ...
setCurrentPlayer(PLAYER);
pthread_cond_signal(&cond);
// NOT HERE pthread_mutex_unlock(&mutex);
}
}
pthread_mutex_unlock(&mutex); // UNLOCK HERE
}
另一个线程也是如此。您应该在等待之前锁定互斥锁,并在发出等待信号后解锁互斥锁,如下所示:
//...
while(!isGameOver()) {
pthread_mutex_lock(&mutex);
if(getCurrentPlayer() != PLAYER) {
pthread_cond_wait(&cond, &mutex);
}
pthread_mutex_unlock(&mutex);
// ...
另见此处:
还有一个注意事项:在调用
pthread_create()之前,应该先运行这两行代码代码>
不能保证线程会在这两行之前执行
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
在关键部分和条件调用周围放置一些日志语句-您可以看到死锁是如何产生的。我猜,getCurrentPlayer()
的值没有正确更新……请尝试使用错误检查互斥体。请参阅上的PTHREAD\u MUTEX\u ERRORCHECK
。我确信更新后的代码应该可以工作。你能给我们看一下getCurrentPlayer()
,setCurrentPlayer()
,以及初始化他们访问的值的代码吗?谢谢你的帮助,但它似乎仍然不起作用。我已经用新代码更新了原来的帖子,它现在似乎在做什么。@shadow:你把锁放在我放的地方了吗?对我有效。应该是而在如果(getCurrentPlayer()!=对手)
中,以避免虚假唤醒。您是否确保将“当前玩家”初始化为玩家
或对手
?如果您的代码被初始化为任何其他值,它将挂起。@MaximYegorushkin:也许,但在这种情况下,它将再次进入睡眠状态。我非常确定互斥锁锁定/解锁应该在while循环之外。