‭‭小豪 2022-10-20 11:53 采纳率: 57.1%
浏览 52
已结题

关于Linux操作系统

嗜睡的理发师问题:一个理发店由一个有N张沙发的等候室和一个放有一张理发椅的理发室组成。没有顾客要理发时,理发师便去睡觉。当一个顾客走进理发店时,如果所有的沙发都已经被占用,他便离开理发店;否则,如果理发师正在为其他顾客理发,则该顾客就找一张空沙发坐下等待;如果理发师因无顾客正在睡觉,则由新到的顾客唤醒理发师为其理发。在理发完成后,顾客必须付费,直到理发师收费后才能离开理发店。帮帮忙,用信号量实习这个同步问题。

  • 写回答

1条回答 默认 最新

  • 光仔December 全栈领域优质创作者 2022-10-21 20:40
    关注

    实现上面的效果,可以使用是“生产者-消费者-仓储”模型,需要实现以下几点:
    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;
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 11月2日
  • 已采纳回答 10月25日
  • 创建了问题 10月20日

悬赏问题

  • ¥15 state显示变量是字符串形式,但是仍然红色,无法引用,并显示类型不匹配
  • ¥20 求一个html代码,有偿
  • ¥100 关于使用MATLAB中copularnd函数的问题
  • ¥20 在虚拟机的pycharm上
  • ¥15 jupyterthemes 设置完毕后没有效果
  • ¥15 matlab图像高斯低通滤波
  • ¥15 针对曲面部件的制孔路径规划,大家有什么思路吗
  • ¥15 钢筋实图交点识别,机器视觉代码
  • ¥15 如何在Linux系统中,但是在window系统上idea里面可以正常运行?(相关搜索:jar包)
  • ¥50 400g qsfp 光模块iphy方案