You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言多线程游戏程序卡顿疑似死锁问题求助与修复

多线程小游戏死锁排查求助

我正在开发一款多线程小游戏,核心逻辑如下:

  • Manager线程创建用户指定数量的Player线程
  • 每轮(轮数由用户设定)中,所有Player线程生成随机数
  • 全部Player完成随机数生成后,Manager线程找出随机数最大的线程并为其加分
  • 游戏结束后,Manager线程输出最终胜者

我编写了对应的C语言代码,但运行时终端卡顿,怀疑程序陷入死锁,特此求助。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

struct Player{
    int isFinished;
    int id;
    int number;
};

struct GameManager{
    struct Player *Players;
    int *WinnersTable;
    int Rounds;
};

struct GameDetails{
    int PlayersCount;
    int RoundsCount;
};

struct GameManager game_manager;
pthread_mutex_t lock;
pthread_cond_t cond;
int IsGameActive;

void* ManagerGameFunc(void* gameDetails);
void* PlayerFunc(void* playerDetails);
void SetWinnerToRound(int roundNumber, int playersCount);
void StartNewRound(int playersCount);
void printWinnerToGame(int playersCount);
int IsRoundEnded(int playersCount);

int main(){
    srand(time(NULL));
    pthread_t ManagerThread;
    pthread_mutex_init(&lock, NULL);
    pthread_cond_init(&cond, NULL);
    struct GameDetails gameDetails;
    printf("----GAME----\n");
    printf("Enter amount of players\n");
    fflush(stdin);
    scanf("%d\n", &gameDetails.PlayersCount);
    printf("Enter amount of rounds\n");
    fflush(stdin);
    scanf("%d\n", &gameDetails.RoundsCount);
    printf("----GAME STARTED----\n");
    pthread_create(&ManagerThread, NULL, ManagerGameFunc, &gameDetails);
    pthread_join(ManagerThread, NULL);
    printf("Game finished\n");
    pthread_mutex_destroy(&lock);
    pthread_cond_destroy(&cond);
}

void* ManagerGameFunc(void* gameDetails){
    struct GameDetails game_details = *((struct GameDetails *)gameDetails);
    pthread_t *threads = (pthread_t *)malloc(game_details.PlayersCount * sizeof(pthread_t));
    game_manager.Players = (struct Player *)malloc(game_details.PlayersCount * sizeof(struct Player));
    game_manager.WinnersTable = (int *)malloc(game_details.PlayersCount * sizeof(int));
    game_manager.Rounds = game_details.RoundsCount;
    IsGameActive = 1;
    for(int i = 0; i < game_details.PlayersCount; i++){
        game_manager.Players[i].isFinished = 0;
        game_manager.Players[i].id = i;
        pthread_create(&threads[i], NULL, PlayerFunc, &game_manager.Players[i]);
    }
    for(int i = 0; i < game_manager.Rounds; i++){
        pthread_mutex_lock(&lock);
        while(!IsRoundEnded(game_details.PlayersCount)){
            pthread_cond_wait(&cond, &lock);
        }
        SetWinnerToRound(i + 1, game_details.PlayersCount);
        StartNewRound(game_details.PlayersCount);
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&lock);
    }
    IsGameActive = 0;
    printf("\nGame end ! The winner of the game is ...\n");
    printWinnerToGame(game_details.PlayersCount);
}

void* PlayerFunc(void* playerDetails){
    struct Player player = *((struct Player *)playerDetails);
    while(IsGameActive){
        pthread_mutex_lock(&lock);
        while(player.isFinished){
            pthread_cond_wait(&cond, &lock);
        }
        player.number = (rand() % (100 - 1 + 1)) + 1;
        printf("%d", player.number);
        player.isFinished = 1;
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&lock);
    }
}

void SetWinnerToRound(int roundNumber, int playersCount){
    int max = game_manager.Players[0].number;
    int id = 0;
    for(int i = 1; i < playersCount; i++){
        if(game_manager.Players[i].number > max){
            max = game_manager.Players[i].number;
            id = i;
        }
    }
    printf("--Round %d: winner is player number %d--\n", roundNumber, id + 1);
    game_manager.WinnersTable[id]++;
}

void StartNewRound(int playersCount){
    for(int i = 1; i < playersCount; i++){
        game_manager.Players[i].isFinished = 0;
    }
}

void printWinnerToGame(int playersCount){
    int max = game_manager.Players[0].number;
    int id = 0;
    for(int i = 1; i < playersCount; i++){
        if(game_manager.Players[i].number > max){
            max = game_manager.Players[i].number;
            id = i;
        }
    }
    printf("Player number %d is the winner of the game !!\n", id + 1);
}

int IsRoundEnded(int playersCount){
    for(int i = 0; i < playersCount; i++)
        if(!game_manager.Players[i].isFinished)
            return 0;
    return 1;
}

问题解决更新

听取建议后,我做了两处修改,程序现已正常运行:

  • 将PlayerFunc中的Player对象改为指针(原代码为拷贝导致修改无效)
  • 将pthread_cond_signal替换为pthread_cond_broadcast

感谢各位帮助!

内容的提问来源于stack exchange,提问作者Avi C

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 23:42:51