课后作业5

第一关 生产者与消费者问题

一.变量声明

#define PRODUCER_NUM 5   //定义生产者数量
#define CONSUMER_NUM 5   //定义消费者数量
sem_t full, empty, mutex1, mutex2   //定义信号量
//full和empty实现生产者和消费者同步
//mutex1实现生产者之间互斥,mutex2实现消费者之间互斥

二.produce函数

void *produce(void *id){               //增加参数:生产者编号,注意为void *类型  
    int i;
    const int pid = *(int*)id;         //类型转换
    for (i = 0; i < PRODUCT_NUM; i++){  
        sleep_random(2);  
        sem_wait(&empty);
        sem_wait(&mutex1);             //生产者之间互斥

        buffer[writepos++] = 1000 * pid + i + 1;   //修改编号 
        if (writepos >= N)  
            writepos = 0;  
        printf("produce:    %d\n", 1000 * pid + i + 1); //修改输出
        
        sem_post(&mutex1);             //生产者之间互斥
        sem_post(&full);  
    }  
}

三.consume函数 

void *consume(void *id){               //增加参数:消费者编号,注意为void *类型
    int i;
    const int cid = *(int*)id;         //类型转换
    for (i = 0; i < PRODUCT_NUM; i++){  
        sleep_random(2);  
        sem_wait(&full);
        sem_wait(&mutex2);             //消费者之间互斥

        printf("%d consume: %d\n", cid, buffer[readpos]);  //修改输出
        buffer[readpos++] =  - 1;  
        if (readpos >= N)  
            readpos = 0;

        sem_post(&mutex2);             //消费者之间互斥
        sem_post(&empty);  
  }  
}

四.main函数

int main(){  
    int i, producer_id[PRODUCER_NUM], consumer_id[CONSUMER_NUM];   //声明存储编号的数组
    pthread_t producer_t[PRODUCER_NUM];   //声明存储线程的数组
    pthread_t consumer_t[CONSUMER_NUM];   //每一个生产者和消费者都有一个线程
    for (i = 0; i < N; i++)  
        buffer[i] =  - 1;  
    srand((int)time(0));
    sem_init(&full, 0, 0);                //信号量初始化
    sem_init(&empty, 0, N);
    sem_init(&mutex1, 0, 1);              //mutex1和mutex2用于实现互斥,故初值为1
    sem_init(&mutex2, 0, 1);
    for (i = 0; i < PRODUCER_NUM; i++){   //创建线程
        producer_id[i] = i + 1;
        pthread_create(&producer_t[i], NULL, produce, &producer_id[i]);
    }
    for (i = 0; i < CONSUMER_NUM; i++){
        consumer_id[i] = i + 1;
        pthread_create(&consumer_t[i], NULL, consume, &consumer_id[i]);
    }
    for (i = 0; i < PRODUCER_NUM; i++)     //等待线程结束
        pthread_join(producer_t[i], NULL);
    for (i = 0; i < CONSUMER_NUM; i++)
        pthread_join(consumer_t[i], NULL);
    return 0;  
}

第二关 三个并发进程

一.变量声明

int buffer_P_Q[M], buffer_Q_R[N], readpos_P_Q = 0, writepos_P_Q = 0, readpos_Q_R = 0, writepos_Q_R = 0;
//缓冲池和各自的读写位置声明加初始化
sem_t full_P_Q, empty_P_Q, full_Q_R, empty_Q_R;
//信号量声明,full_P_Q和empty_P_Q实现PQ同步,full_Q_R和empty_Q_R实现QR同步

二.P函数

sem_wait(&empty_P_Q);                   //实现PQ同步
buffer_P_Q[writepos_P_Q++] = i + 1;     //读取信息放入缓冲池1
if (writepos_P_Q >= M)                  //放满了,重置
    writepos_P_Q = 0;
printf("sends:        %d\n", i + 1);    //打印读取的信息
sem_post(&full_P_Q);                    //实现PQ同步

三.Q函数

sem_wait(&full_P_Q);                //实现PQ同步
data = buffer_P_Q[readpos_P_Q];     //从缓冲池1中读取信息
buffer_P_Q[readpos_P_Q] = -1;       //表示信息已被读走
readpos_P_Q++;
if (readpos_P_Q >= M)               //重置
    readpos_P_Q = 0;
sem_post(&empty_P_Q);               //实现PQ同步

sem_wait(&empty_Q_R);               //实现QR同步
buffer_Q_R[writepos_Q_R++] = data;  //将读取的信息放进缓冲池2
if (writepos_Q_R >= N)              //重置
    writepos_Q_R = 0;
sem_post(&full_Q_R);                //实现QR同步

三.R函数

sem_wait(&full_Q_R);                                  //实现QR同步
printf("receives:    %d\n", buffer_Q_R[readpos_Q_R]); //输出信息
buffer_Q_R[readpos_Q_R++] = -1;                       //表示信息已被读走
if (readpos_Q_R >= N)                                 //重置
    readpos_Q_R = 0;
sem_post(&empty_P_Q);                                 //实现QR同步

四.main函数

sem_init(&full_P_Q, 0, 0);   //信号量初始化
sem_init(&empty_P_Q, 0, M);
sem_init(&full_Q_R, 0, 0);
sem_init(&empty_Q_R, 0, N);

第三关 理发师问题

一.变量声明

sem_t start, finish, empty_rest, empty_cut;
//信号量声明,start和finish实现“顾客进入理发室”和“理发师理发(barber)”过程的同步
//empty_rest实现进入休息室的顾客之间的互斥,empty_cut实现进入理发室的顾客之间的互斥

二.barber函数

sem_wait(&start);   //实现“顾客进入理发室”和“理发师理发(barber)”过程的同步
sem_post(&finish);

三.customer函数 

 

sem_wait(&empty_rest)可理解为:休息室没有空位时必须等待

sem_wait(&empty_cut)可理解为:理发室没有空位时必须等待

sem_post(&empty_rest)可理解为:顾客已进入理发室,所以“顾客进入休息室”过程已结束,可以把“锁”解开了

sem_post(&start)是保证“顾客进入休息室”在“理发师为该顾客理发”之前发生

sem_wait(&finish)可理解为:顾客进入了理发室,但需要等待理发师给上一个顾客理完

sem_post(&empty_cut)可理解为:顾客开始理发,以“顾客进入理发室”过程已结束,可以把“锁”解开了

四.main函数

sem_init(&start ,0 ,0);      //empty_rest和empty_cut是实现同步的信号量,故初值应为1
sem_init(&finish ,0 ,0);
sem_init(&empty_rest ,0 ,2); //休息室有2个位置
sem_init(&empty_cut ,0 ,1);  //理发室有1个位置

注意:

1.只能在原文件基础上修改,不能创建新的文件。

2.修改完毕后,在/data/workspace/myshixun/exp3目录下使用gcc 4-x.c -pthread编译,然后可以用./a.out运行测试。评测前要把修改后的4-x.c文件拷贝到/myshixun目录下,否则会报错找不到文件。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值