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

调用pthread_create触发段错误:Dining Philosophers问题模拟代码故障

解决 Dining Philosophers 问题中的线程同步与死锁问题

看起来你在实现经典的 Dining Philosophers 问题时遇到了麻烦,我先帮你梳理这段代码常见的漏洞,再给出完整的可运行修正实现。

原代码的核心问题

你给出的代码只定义了基础的同步变量和不完整的test函数,缺少了哲学家拿/放叉子的核心逻辑、线程入口函数,也没有处理同步原语的初始化/销毁,这些缺失很容易导致死锁、线程状态异常等问题。

完整修正后的代码

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

// 创建互斥锁、条件变量及状态变量
pthread_mutex_t mutex;
pthread_cond_t cond_var[5];
enum { THINKING, HUNGRY, EATING } state[5];

// 测试是否可获取叉子(核心判断逻辑)
void test(int pNumber) {
    // 仅当自己饥饿,且左右邻居都不在吃饭时,才能拿起叉子
    if (state[pNumber] == HUNGRY &&
        state[(pNumber + 4) % 5] != EATING &&
        state[(pNumber + 1) % 5] != EATING) {
        state[pNumber] = EATING;
        // 唤醒当前等待的哲学家(不用再等了,可以吃饭)
        pthread_cond_signal(&cond_var[pNumber]);
    }
}

// 拿起叉子的操作
void pickup(int pNumber) {
    pthread_mutex_lock(&mutex);
    state[pNumber] = HUNGRY;
    printf("哲学家 %d 感到饥饿,尝试拿叉子\n", pNumber);
    // 先检查是否能直接拿到叉子
    test(pNumber);
    // 如果没拿到,就进入条件等待(等待时会自动释放互斥锁,被唤醒后重新获取锁)
    while (state[pNumber] != EATING) {
        pthread_cond_wait(&cond_var[pNumber], &mutex);
    }
    pthread_mutex_unlock(&mutex);
}

// 放下叉子的操作
void putdown(int pNumber) {
    pthread_mutex_lock(&mutex);
    state[pNumber] = THINKING;
    printf("哲学家 %d 吃完了,放下叉子\n", pNumber);
    // 通知左右邻居:我吃完了,你们可以试试拿叉子了
    test((pNumber + 4) % 5);
    test((pNumber + 1) % 5);
    pthread_mutex_unlock(&mutex);
}

// 哲学家的线程主体(循环:思考→饥饿→吃饭)
void* philosopher(void* arg) {
    int pNumber = *(int*)arg;
    free(arg); // 释放传入的参数内存

    while (1) {
        // 思考阶段(随机时长模拟)
        printf("哲学家 %d 正在思考\n", pNumber);
        sleep(rand() % 3);

        // 尝试拿叉子吃饭
        pickup(pNumber);
        printf("哲学家 %d 开始吃饭\n", pNumber);
        sleep(rand() % 2);

        // 吃完放下叉子
        putdown(pNumber);
    }
    return NULL;
}

int main() {
    pthread_t threads[5];
    int i;

    // 初始化互斥锁和所有条件变量
    pthread_mutex_init(&mutex, NULL);
    for (i = 0; i < 5; i++) {
        pthread_cond_init(&cond_var[i], NULL);
        state[i] = THINKING; // 初始状态都是思考
    }

    // 创建5个哲学家线程
    for (i = 0; i < 5; i++) {
        int* pNumber = malloc(sizeof(int));
        *pNumber = i;
        pthread_create(&threads[i], NULL, philosopher, pNumber);
    }

    // 等待所有线程(程序会一直运行,除非手动终止)
    for (i = 0; i < 5; i++) {
        pthread_join(threads[i], NULL);
    }

    // 销毁同步原语(实际这里不会执行到,因为线程是无限循环)
    pthread_mutex_destroy(&mutex);
    for (i = 0; i < 5; i++) {
        pthread_cond_destroy(&cond_var[i]);
    }

    return 0;
}

关键逻辑说明

  • test函数:这是避免死锁的核心——它确保只有当哲学家的左右邻居都不在吃饭时,才允许当前哲学家拿起叉子,彻底杜绝了所有哲学家同时拿左叉子导致的死锁场景。
  • pickup/putdown函数:通过互斥锁保护共享的state数组,确保状态修改的原子性;putdown后主动通知邻居检查状态,避免线程无限等待。
  • 线程主体:用随机睡眠模拟思考和吃饭的时长,更贴近真实场景的并发行为。

内容的提问来源于stack exchange,提问作者N Sharrett

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:23:46