简体   繁体   English

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

[英]C++ game: pthread_cond_signal doesn't wake up opponent thread

I'm making a game where the user plays against the computer. 我正在制作一个用户与电脑对战的游戏。 The computer opponent thinks about its next move while it is the player's turn. 计算机对手在轮到玩家的同时考虑下一步行动。 If the player moves to the spot where the computer opponent was planning to move, the computer opponent starts its search for its move over again. 如果玩家移动到计算机对手计划移动的位置,则计算机对手开始搜索其再次移动。

Here's an outline of the main function and the opponent function: 这是主要功能和对手功能的概述:

[UPDATED] [更新]

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);
    }
}

Currently, it seems like this is what is happening: [UPDATED] 目前,似乎正是这样:[更新]

  • the opponent finds his move (findMove) 对手发现他的举动(findMove)
  • the opponent locks the mutex (pthread_mutex_lock) 对手锁定互斥锁(pthread_mutex_lock)
  • the opponent starts waiting (pthread_cond_wait) 对手开始等待(pthread_cond_wait)
  • the main function locks the mutex (pthread_mutex_lock) main函数锁定互斥锁(pthread_mutex_lock)
  • the player makes his move 玩家动作
  • the main thread signals that it is the opponents turn (pthread_cond_signal) 主线程表明它是对手转身(pthread_cond_signal)

Then, nothing happens. 然后,没有任何反应。

What I want to happen (with the mutex being locked in appropriate places): 我想要发生什么(将互斥锁锁定在适当的位置):

  • the opponent finds his move (findMove) 对手发现他的举动(findMove)
  • the opponent starts waiting (pthread_cond_wait) 对手开始等待(pthread_cond_wait)
  • the player makes his move 玩家动作
  • the main thread signals that it is the opponents turn (pthread_cond_signal) 主线程表明它是对手转身(pthread_cond_signal)
  • the opponent stops waiting 对手停止等待
  • the opponent makes the move it was previously thinking about 对手做出了以前想过的举动
  • the opponent switches the current player (setCurrentPlayer) 对手切换当前玩家(setCurrentPlayer)
  • repeat 重复

I'm not really experienced with threads, so could someone help me out with what is going on here, and how I could possibly fix it? 我对线程并不是很有经验,所以有人可以帮助我解决这里发生的事情,以及我如何解决这个问题? I don't know if I have the mutex lock/unlock, condition signal/wait, and setCurrentPlayer functions in the right places. 我不知道我是否在正确的位置有互斥锁定/解锁,条件信号/等待和setCurrentPlayer功能。

The mutex should be locked when you call pthread_cond_wait - that function atomically unlocks the mutex, waits for a signal, and relocks the mutex before returning. 调用pthread_cond_wait时应该锁定互斥锁 - 该函数以原子方式解锁互斥锁,等待信号,并在返回之前重新锁定互斥锁。 The purpose of the mutex is to serialise access to the shared state (in this case the current player), so it should be locked around any access to that. 互斥锁的目的是序列化对共享状态的访问(在这种情况下是当前播放器),因此应该锁定对它的任何访问。 The loop should be more like: 循环应该更像:

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
}

and similarly for the other thread. 和其他线程类似。

You should lock the mutex before the wait and unlock it after wait is signaled, like this: 您应该在等待之前 锁定互斥锁并在发出等待信号后将其解锁,如下所示:

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

See also here: https://computing.llnl.gov/tutorials/pthreads/ 另见: https//computing.llnl.gov/tutorials/pthreads/

They have quite understandable examples there. 他们在那里有很容易理解的例子。

Another note: you should have run these two lines before calling pthread_create(); 另一个注意事项:在调用pthread_create();之前,你应该运行这两行pthread_create(); There is no guarantee that your thread will be executed before these two lines. 无法保证在这两行之前执行您的线程。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM