4.15刷题

10-23
# 目重述 4.15 "理发师睡觉"问:假设理发店由一个有 $n$ 个座位的等待间和一个理发间(仅有一个座位)组成。当没有顾客时,理发师睡觉。顾客到来后,若等待间有空座则坐下等待;否则离开。当顾客进入理发间发现理发师正在睡觉时,会叫醒理发师理发。理发完成后,顾客离开,理发师继续睡直到下一个顾客到来。请编写程序模拟该过程。 # 给出答案(带注释的代码块) ```c #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> #define NUM_SEATS 5 // 等待间座位数 #define MAX_CUSTOMERS 10 // 最大顾客数 // 信号量定义 sem_t barber_ready; // 理发师是否准备好 (1: 准备好, 0: 睡觉/忙碌) sem_t customer_arrived; // 顾客是否到达 (0: 无人, >0: 有顾客等待) sem_t mutex; // 互斥锁,保护共享变量 int waiting_customers = 0; // 当前等待的顾客数量 // 理发师线程函数 void* barber(void* arg) { while (1) { printf("理发师:现在没有顾客,我去睡觉...\n"); // 等待顾客到达 sem_wait(&customer_arrived); // 获得互斥锁 sem_wait(&mutex); waiting_customers--; printf("理发师:开始为顾客理发,剩余等待顾客:%d\n", waiting_customers); sem_post(&mutex); // 开始理发(占用时间) printf("理发师:正在理发...\n"); sleep(2); // 模拟理发耗时 // 理发完成,通知顾客已完成 sem_post(&barber_ready); printf("理发师:理发完成。\n"); } return NULL; } // 顾客线程函数 void* customer(void* arg) { long id = (long)arg; printf("顾客 %ld:到达理发店。\n", id); sem_wait(&mutex); if (waiting_customers < NUM_SEATS) { waiting_customers++; printf("顾客 %ld:在等待区坐下,当前等待人数:%d\n", id, waiting_customers); // 通知理发师有顾客到达 sem_post(&customer_arrived); sem_post(&mutex); // 等待理发师准备好给自己理发 sem_wait(&barber_ready); printf("顾客 %ld:正在被理发...\n", id); printf("顾客 %ld:理发结束,离开。\n", id); } else { // 等待区已满,顾客离开 sem_post(&mutex); printf("顾客 %ld:等待区已满,离开。\n", id); } return NULL; } int main() { pthread_t barber_thread; pthread_t customer_threads[MAX_CUSTOMERS]; // 初始化信号量 sem_init(&barber_ready, 0, 0); sem_init(&customer_arrived, 0, 0); sem_init(&mutex, 0, 1); // 创建理发师线程 pthread_create(&barber_thread, NULL, barber, NULL); // 创建多个顾客线程 for (long i = 0; i < MAX_CUSTOMERS; i++) { pthread_create(&customer_threads[i], NULL, customer, (void*)i); sleep(1); // 模拟顾客陆续到达 } // 等待所有顾客线程结束 for (int i = 0; i < MAX_CUSTOMERS; i++) { pthread_join(customer_threads[i], NULL); } // 不终止理发师线程,实际中可用标志位控制退出 pthread_cancel(barber_thread); pthread_join(barber_thread, NULL); // 销毁信号量 sem_destroy(&barber_ready); sem_destroy(&customer_arrived); sem_destroy(&mutex); return 0; } ``` # 代码解析 - 使用 `semaphore` 实现同步:`customer_arrived` 表示是否有顾客到达,`barber_ready` 表示理发师是否可以服务下一位顾客,`mutex` 保证对共享变量 `waiting_customers` 的互斥访问。 - 理发师线程循环执行:等待顾客 → 减少等待计数 → 理发 → 释放资源。 - 顾客线程尝试进入:获取锁 → 检查座位 → 若有空位则留下并唤醒理发师,否则离开。 - 利用 POSIX 线程 (`pthread`) 模拟并发行为,`sleep()` 模拟事件延迟。 # 知识点 - **信号量(Semaphore)**:用于进程/线程间同步,通过 `wait()` 和 `post()` 操作实现资源控制与通信。 - **互斥锁(Mutex)**:确保同一时间只有一个线程访问临界区,防止数据竞争。 - **生产者-消费者模型变种**:本是有限缓冲区的特殊形式,顾客为生产者,理发师为消费者。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值