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

基于pthreads与mutex的桥梁调度编程作业技术求助

问题描述

需实现一个基于pthreads与mutex的C++调度程序,核心需求如下:

  • 读取输入文件:首行Bridge 升桥时间 降桥时间,后续每行Car/Boat 名称 到达间隔时间 通行时间
  • 调度规则:
    • 同一时间仅允许一个车/船通行
    • 若队列中同时有车和船,交替通行(切换类型时需升降桥,sleep对应时长)
    • 若仅有一种类型等待,连续通行无需升降桥
  • 要求为每个到达的车/船创建独立线程,通行完成后销毁线程

已完成输入读取并将数据存入vector<node>,需补充核心调度逻辑。

核心实现思路与代码修改

1. 修正全局变量与补充必要定义

补全缺失的条件变量,调整桥状态定义,增加共享调度变量:

#include <string>
#include <vector>
#include <fstream>
#include <pthread.h>
#include <unistd.h>  // 用于sleep函数

using namespace std;

static pthread_mutex_t theLock;
static pthread_cond_t carCanGo;
static pthread_cond_t shipCanGo;

int bridge_up_time;    // 桥升起所需时间
int bridge_down_time;  // 桥降下所需时间
bool bridge_is_down = true;  // 初始桥放下,供车辆通行
string last_passed_type = "Car";  // 记录上一个通行的类型,初始默认车辆
int waiting_cars = 0;   // 等待的车辆数
int waiting_ships = 0;  // 等待的船只数

struct node {
    string type;
    int arrival_interval;
    int pass_time;
    string name;

    node(string t, int ai, int pt, string n) 
        : type(t), arrival_interval(ai), pass_time(pt), name(n) {}
};

// 线程参数结构体:传递node数据
struct ThreadData {
    node* vehicle;
};

2. 实现线程核心逻辑函数

编写符合pthread签名的线程函数,处理车辆/船只的通行调度:

void* vehicle_thread(void* arg) {
    ThreadData* data = (ThreadData*)arg;
    node* v = data->vehicle;
    pthread_mutex_lock(&theLock);

    if (v->type == "Car") {
        waiting_cars++;
        // 等待条件:桥已放下,且要么没有船只等待,要么轮到车辆通行
        while (!bridge_is_down || (waiting_ships > 0 && last_passed_type == "Boat")) {
            pthread_cond_wait(&carCanGo, &theLock);
        }
        waiting_cars--;

        // 如果上一个通行的是船只,需要先降下桥
        if (last_passed_type == "Boat") {
            printf("Lowering bridge for %s...\n", v->name.c_str());
            pthread_mutex_unlock(&theLock);
            sleep(bridge_down_time);
            pthread_mutex_lock(&theLock);
            bridge_is_down = true;
            last_passed_type = "Car";
        }

        // 开始通行
        printf("%s starts crossing the bridge\n", v->name.c_str());
        pthread_mutex_unlock(&theLock);
        sleep(v->pass_time);
        pthread_mutex_lock(&theLock);
        printf("%s finishes crossing the bridge\n", v->name.c_str());

        // 唤醒下一个等待的线程
        if (waiting_ships > 0) {
            pthread_cond_signal(&shipCanGo);
        } else if (waiting_cars > 0) {
            pthread_cond_signal(&carCanGo);
        }
    } else { // Boat
        waiting_ships++;
        // 等待条件:桥已升起,且要么没有车辆等待,要么轮到船只通行
        while (bridge_is_down || (waiting_cars > 0 && last_passed_type == "Car")) {
            pthread_cond_wait(&shipCanGo, &theLock);
        }
        waiting_ships--;

        // 如果上一个通行的是车辆,需要先升起桥
        if (last_passed_type == "Car") {
            printf("Raising bridge for %s...\n", v->name.c_str());
            pthread_mutex_unlock(&theLock);
            sleep(bridge_up_time);
            pthread_mutex_lock(&theLock);
            bridge_is_down = false;
            last_passed_type = "Boat";
        }

        // 开始通行
        printf("%s starts passing through the channel\n", v->name.c_str());
        pthread_mutex_unlock(&theLock);
        sleep(v->pass_time);
        pthread_mutex_lock(&theLock);
        printf("%s finishes passing through the channel\n", v->name.c_str());

        // 唤醒下一个等待的线程
        if (waiting_cars > 0) {
            pthread_cond_signal(&carCanGo);
        } else if (waiting_ships > 0) {
            pthread_cond_signal(&shipCanGo);
        }
    }

    pthread_mutex_unlock(&theLock);
    delete data;
    return NULL;
}

3. 主函数中创建线程并模拟到达间隔

在输入读取完成后,添加线程创建逻辑,按照到达间隔时间依次启动线程:

int main() {
    pthread_mutex_init(&theLock, NULL);
    pthread_cond_init(&carCanGo, NULL);
    pthread_cond_init(&shipCanGo, NULL);

    vector<node*> theList;
    string fileName;
    cin >> fileName;
    fstream theFile(fileName);
    if (!theFile.is_open()) {
        cout << "Error opening file!" << endl;
        return 1;
    }

    // 读取首行桥参数
    string dummy;
    theFile >> dummy >> bridge_up_time >> bridge_down_time;

    // 读取后续车辆/船只数据
    string type, name;
    int arrival_interval, pass_time;
    while (theFile >> type >> name >> arrival_interval >> pass_time) {
        theList.push_back(new node(type, arrival_interval, pass_time, name));
    }

    // 创建线程并按到达间隔启动
    vector<pthread_t> threads;
    for (size_t i = 0; i < theList.size(); i++) {
        // 等待到达间隔时间(第一个无需等待)
        if (i > 0) {
            sleep(theList[i]->arrival_interval);
        }

        ThreadData* data = new ThreadData();
        data->vehicle = theList[i];
        pthread_t tid;
        pthread_create(&tid, NULL, vehicle_thread, (void*)data);
        threads.push_back(tid);
    }

    // 等待所有线程完成
    for (pthread_t tid : threads) {
        pthread_join(tid, NULL);
    }

    // 清理资源
    pthread_mutex_destroy(&theLock);
    pthread_cond_destroy(&carCanGo);
    pthread_cond_destroy(&shipCanGo);
    for (node* n : theList) {
        delete n;
    }

    return 0;
}
关键逻辑说明
  • 互斥锁theLock:保护所有共享变量(桥状态、等待计数、上一通行类型),避免多线程竞争
  • 条件变量carCanGo/shipCanGo:让等待的线程休眠,直到满足通行条件(桥状态正确、轮到当前类型通行)
  • 交替通行实现:通过last_passed_type记录上一个通行类型,当存在另一种类型等待时,切换类型前触发桥升降
  • 连续通行优化:同类型等待时,无需升降桥,直接唤醒下一个同类型线程
  • 到达间隔模拟:主函数中按输入的间隔时间依次启动线程,模拟真实到达顺序

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 03:07:56