基于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
相关产品推荐
相关产品推荐

