C ++游戏:pthread_cond_signal不会唤醒对手线程

时间:2011-11-03 17:12:44

标签: 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;
    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_mutex_lock)
  • 对手开始等待(pthread_cond_wait)
  • 主函数锁定互斥锁(pthread_mutex_lock)
  • 玩家移动
  • 主线程表明它是对手转(pthread_cond_signal)

然后,没有任何反应。

我想要发生什么(将互斥锁锁定在适当的位置):

  • 对手发现他的动作(findMove)
  • 对手开始等待(pthread_cond_wait)
  • 玩家移动
  • 主线程表明它是对手转(pthread_cond_signal)
  • 对手停止等待
  • 对手做出之前想过的举动
  • 对手切换当前玩家(setCurrentPlayer)
  • 重复

我对线程并不是很有经验,所以有人可以帮助我解决这里发生的事情,以及我如何解决这个问题?我不知道我是否在正确的位置有互斥锁定/解锁,条件信号/等待和setCurrentPlayer功能。

3 个答案:

答案 0 :(得分:2)

当您调用pthread_cond_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
}

和其他线程类似。

答案 1 :(得分:1)

在等待之前你应该锁定 等待并在等待信号后将其解锁,如下所示:

 //...
  while(!isGameOver()) {
        pthread_mutex_lock(&mutex);
        if(getCurrentPlayer() != PLAYER) {
            pthread_cond_wait(&cond, &mutex);
        }
        pthread_mutex_unlock(&mutex);
  // ...

另见:https://computing.llnl.gov/tutorials/pthreads/

他们在那里有很容易理解的例子。

答案 2 :(得分:1)

另一个注意事项:在调用pthread_create();之前,您应该运行这两行 无法保证在这两行之前执行您的线程。

pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);