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

C语言pthread线程模拟航母起降程序并行异常排查

问题排查与修正方案

核心问题分析

你的代码存在两个关键问题,导致线程串行且起飞逻辑不符合预期:

1. 互斥锁持有时间过长,强制线程串行

降落和起飞线程中,Sleep(1000)(模拟起降耗时)以及非共享变量的printf操作都被放在了互斥锁的保护范围内。这意味着线程在执行耗时的模拟操作时,一直持有锁,其他线程完全无法获取锁进入临界区,必然导致串行执行。

互斥锁的作用仅应保护共享变量planes_on_deck的读写操作,耗时的业务逻辑(起降模拟)应该放在锁的范围之外。

2. 起飞线程无法及时感知条件变化

由于降落线程长期持有锁,即使planes_on_deck增长到K以上,起飞线程也无法获取锁进入临界区检查条件。只有当甲板被填满到N时,降落线程触发pthread_cond_wait释放锁,起飞线程才有机会执行,这完全违背了你的设计预期。

修正后的代码

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define N 15 // 航母甲板容量
#define K 9 // 降落优先级阈值:甲板飞机数小于K时,降落优先
#define S 1 

pthread_mutex_t mutex;
pthread_cond_t landing_cond;
pthread_cond_t takeoff_cond;

int planes_on_deck = 0;

void* landing() {
    while(1) {
        pthread_mutex_lock(&mutex);

        // 甲板满时等待
        while (planes_on_deck >= N) {
            pthread_cond_wait(&landing_cond, &mutex);
        }
        // 仅在锁内修改共享变量
        planes_on_deck++;
        printf("landing.\n");
        // 修改完成后立即广播,通知起飞线程条件变化
        pthread_cond_broadcast(&takeoff_cond);
        pthread_mutex_unlock(&mutex);

        // 耗时的起降模拟放在锁外,不阻塞其他线程
        Sleep(1000);
        // 打印当前飞机数(非共享操作,无需锁)
        printf("number of planes on carrier: %d\n\n", planes_on_deck);       
    }
    return NULL;
}

void* takeoff() {
    while(1) {
        pthread_mutex_lock(&mutex);
        // 甲板飞机数小于K时等待,保证降落优先
        while (planes_on_deck < K) {   
           pthread_cond_wait(&takeoff_cond, &mutex);
        }
        // 仅在锁内修改共享变量
        planes_on_deck--;
        printf("takeoff.\n");
        // 修改完成后立即广播,通知降落线程条件变化
        pthread_cond_broadcast(&landing_cond);
        pthread_mutex_unlock(&mutex);

        // 耗时的起飞模拟放在锁外
        Sleep(1000);
        printf("number of planes on carrier: %d\n\n", planes_on_deck);
    }
    return NULL;
}

int main() {
    printf("number of planes on carrier: %d\n", planes_on_deck);
    pthread_t landing_threads[S];
    pthread_t takeoff_threads[S];

    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&landing_cond, NULL);
    pthread_cond_init(&takeoff_cond, NULL);

    for (int i = 0; i < S; i++){
        if (pthread_create(&landing_threads[i], NULL, landing, NULL) != 0){
            perror("fail to create landing thread");
        }
        if (pthread_create(&takeoff_threads[i], NULL, takeoff, NULL) != 0){
            perror("fail to create takeoff thread");
        }       
    }

    for (int i = 0; i < S; i++){
        if (pthread_join(takeoff_threads[i], NULL) != 0){
            return 2;
        }
        if (pthread_join(landing_threads[i], NULL) != 0){
            return 2;
        }
    }

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&landing_cond);
    pthread_cond_destroy(&takeoff_cond);

    return 0;
}

关键修改说明

  • 缩小锁的作用范围:仅在修改和检查共享变量planes_on_deck时持有锁,将Sleep和非共享的打印操作移到锁外,让多个线程可以并行执行耗时的模拟逻辑。
  • 调整广播时机:在修改完planes_on_deck后、解锁前调用pthread_cond_broadcast,确保其他等待的线程能及时感知条件变化,避免解锁后广播可能导致的延迟。
  • 明确优先级逻辑:起飞线程在planes_on_deck < K时持续等待,保证当甲板飞机数不足K时,降落线程可以优先执行,符合设计预期。

内容的提问来源于stack exchange,提问作者wojtek c

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 11:05:18