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

发布于 2024-12-13 16:13:31 字数 2109 浏览 5 评论 0原文

我正在制作一款用户与计算机对战的游戏。轮到玩家时,计算机对手会考虑下一步行动。如果玩家移动到计算机对手计划移动的位置,计算机对手将再次开始搜索其移动。

以下是主函数和对手函数的概述:

[更新]

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 函数是否在正确的位置。

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)
  • the opponent locks the mutex (pthread_mutex_lock)
  • the opponent starts waiting (pthread_cond_wait)
  • the main function locks the mutex (pthread_mutex_lock)
  • the player makes his move
  • the main thread signals that it is the opponents turn (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)
  • the opponent starts waiting (pthread_cond_wait)
  • the player makes his move
  • the main thread signals that it is the opponents turn (pthread_cond_signal)
  • the opponent stops waiting
  • the opponent makes the move it was previously thinking about
  • the opponent switches the current player (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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

无畏 2024-12-20 16:13:31

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

对于其他线程也类似。

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. 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.

梦途 2024-12-20 16:13:31

您应该在等待之前锁定互斥体,并在发出等待信号后解锁它,如下所示:

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

另请参阅此处:https://computing.llnl.gov/tutorials/pthreads/

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

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/

They have quite understandable examples there.

若水般的淡然安静女子 2024-12-20 16:13:31

另请注意:您应该在调用 pthread_create(); 之前运行这两行代码;
无法保证您的线程将在这两行之前执行。

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

Another note: you should have run these two lines before calling 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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文