嗜睡的理发师问题:一个理发店由一个有N张沙发的等候室和一个放有一张理发椅的理发室组成。没有顾客要理发时,理发师便去睡觉。当一个顾客走进理发店时,如果所有的沙发都已经被占用,他便离开理发店;否则,如果理发师正在为其他顾客理发,则该顾客就找一张空沙发坐下等待;如果理发师因无顾客正在睡觉,则由新到的顾客唤醒理发师为其理发。在理发完成后,顾客必须付费,直到理发师收费后才能离开理发店。帮帮忙,用信号量实习这个同步问题。
1条回答 默认 最新
关注 实现上面的效果,可以使用是“生产者-消费者-仓储”模型,需要实现以下几点:
1、顾客仅仅在座位未满时候入座,座位满了满则停止入店。
2、理发师仅仅在座位有顾客时候才能消费,座位空则等待。
3、当理发师发现座位没顾客可服务时候会通知顾客进店落座。
4、顾客在落座后,也需要通知睡觉的理发师来服务。
具体实现代码如下:
第一个是.hpp代码:#pragma once #include <iostream> #include <vector> #include <semaphore.h> #include<pthread.h> using namespace std; namespace ns_cq { pthread_mutex_t p_mtx; pthread_mutex_t c_mtx; const int default_cap = 10; template <class T> class CircularQueue { private: int _cap; vector<T> _circul_queue; //顾客关心空位置的资源 sem_t _blank_sem; //理发师关心位置有顾客的资源 sem_t _data_sem; //用vector模拟环形队列 int _c_step; int _p_step; public: CircularQueue(int cap = default_cap) : _cap(cap), _circul_queue(cap) { //顾客信号量初始化,初始时顾客能申请的信号量为10,因为有10个空位置 sem_init(&_blank_sem, 0, _cap); //理发师信号量初始化,初始时理发师申请到的信号量为0,因为没有顾客坐位置 sem_init(&_data_sem, 0, 0); _c_step = 0; _p_step = 0; pthread_mutex_init(&p_mtx, nullptr); pthread_mutex_init(&c_mtx, nullptr); } ~CircularQueue() { //信号量销毁 sem_destroy(&_blank_sem); sem_destroy(&_data_sem); pthread_mutex_destroy(&p_mtx); pthread_mutex_destroy(&c_mtx); } public: void Push(const T &in) { //客户申请信号量(P操作) 相当于空座位的计数器-- sem_wait(&_blank_sem); //把锁加在申请信号量后,能让多个线程并发申请信号量,然后再竞争锁,省去了单独申请信号量的时间,效率提高 pthread_mutex_lock(&p_mtx); _circul_queue[_p_step] = in; //客户做到空座位后,更新已做人座位的下标 _p_step++; _p_step %= _cap; pthread_mutex_unlock(&p_mtx); //释放信号量(V操作) 相当于有客户坐的座位的计数器++ sem_post(&_data_sem); } void Pop(T *out) { //理发师申请信号量(P操作) 相当于有客户坐的座位的计数器-- sem_wait(&_data_sem); pthread_mutex_lock(&c_mtx); *out = _circul_queue[_c_step]; _c_step++; _c_step %= _cap; pthread_mutex_unlock(&c_mtx); //释放信号量(V操作) 相当于空座位的计数器++ sem_post(&_blank_sem); } }; }
第二个是.cpp代码:
#include <iostream> using namespace std; #include "Circular_queue.hpp" using namespace ns_cq; using namespace ns_task; #include <pthread.h> #include <unistd.h> #include <time.h> #include "task.hpp" void *Consumer(void *args) { CircularQueue<Task> *cq = (CircularQueue<Task> *)args; while (true) { // sleep(1); Task t; cq->Pop(&t); t.Run(); sleep(1); } } void *Producter(void *args) { CircularQueue<Task> *cq = (CircularQueue<Task> *)args; while (true) { sleep(1); cout << " 有一个顾客入店落座了!快醒醒" << endl; cq->Push(t); } } int main() { srand((long long)time(nullptr)); pthread_t c0, c1, c2, c3, p0, p1, p2, p3; CircularQueue<Task> *cq = new CircularQueue<Task>(); pthread_create(&c0, nullptr, Consumer, (void *)cq); pthread_create(&c1, nullptr, Consumer, (void *)cq); pthread_create(&c2, nullptr, Consumer, (void *)cq); pthread_create(&c3, nullptr, Consumer, (void *)cq); pthread_create(&p0, nullptr, Producter, (void *)cq); pthread_create(&p1, nullptr, Producter, (void *)cq); pthread_create(&p2, nullptr, Producter, (void *)cq); pthread_create(&p3, nullptr, Producter, (void *)cq); pthread_join(c0, nullptr); pthread_join(c1, nullptr); pthread_join(c2, nullptr); pthread_join(c3, nullptr); pthread_join(p0, nullptr); pthread_join(p1, nullptr); pthread_join(p2, nullptr); pthread_join(p3, nullptr); return 0; }
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报 编辑记录
悬赏问题
- ¥15 state显示变量是字符串形式,但是仍然红色,无法引用,并显示类型不匹配
- ¥20 求一个html代码,有偿
- ¥100 关于使用MATLAB中copularnd函数的问题
- ¥20 在虚拟机的pycharm上
- ¥15 jupyterthemes 设置完毕后没有效果
- ¥15 matlab图像高斯低通滤波
- ¥15 针对曲面部件的制孔路径规划,大家有什么思路吗
- ¥15 钢筋实图交点识别,机器视觉代码
- ¥15 如何在Linux系统中,但是在window系统上idea里面可以正常运行?(相关搜索:jar包)
- ¥50 400g qsfp 光模块iphy方案