多线程|pc2.c 使用信号量解决生产者、计算者、消费者问题

1.题目要求

使用信号量解决生产者、计算者、消费者问题

  • 功能和前面的实验相同,使用信号量解决

2.解决思路

生产者、计算者、消费者三个线程的逻辑与上一题使用条件变量解决生产者、计算者、消费者问题相同,不同之处在于本题使用条件变量实现信号量sema_tvalue记录了信号量的值。sema_wait函数如果信号量的值小于等于0,则等待条件变量将信号量的值减一。sema_signal函数将信号量的值加一,唤醒等待条件变量的线程。定义mutex_sema用于互斥访问共享缓冲区变量in/outempty_buffer_sema/full_buffer_sema用于线程同步(对buffer1buffer2分别定义上述若干个变量)。在main函数中进行sema_init初始化操作,在生产者、计算者、消费者线程函数中可以直接调用sema_waitsema_signal进行申请信号量和释放信号量。

3.代码

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

#define CAPACITY 4
#define ITEM_COUNT 8
int buffer1[CAPACITY], buffer2[CAPACITY];
int in1, in2;
int out1, out2;

typedef struct {
  int value;
  pthread_mutex_t mutex;
  pthread_cond_t cond;
} sema_t;
sema_t mutex1_sema, mutex2_sema;
sema_t empty_buffer1_sema, empty_buffer2_sema;
sema_t full_buffer1_sema, full_buffer2_sema;


// buffer1
int buffer1_is_empty() {
  return in1 == out1;
}

int buffer1_is_full() {
  return (in1 + 1) % CAPACITY == out1;
}

int get_item1() {
  int item = buffer1[out1];
  out1 = (out1 + 1) % CAPACITY;
  return item;
}

void put_item1(int item) {
  buffer1[in1] = item;
  in1 = (in1 + 1) % CAPACITY;
}

// buffer2
int buffer2_is_empty() {
  return in2 == out2;
}

int buffer2_is_full() {
  return (in2 + 1) % CAPACITY == out2;
}

int get_item2() {
  int item = buffer2[out2];
  out2 = (out2 + 1) % CAPACITY;
  return item;
}

void put_item2(int item) {
  buffer2[in2] = item;
  in2 = (in2 + 1) % CAPACITY;
}


// sema
void sema_init(sema_t *sema, int value) {
  sema->value = value;
  pthread_mutex_init(&sema->mutex, NULL);
  pthread_cond_init(&sema->cond, NULL);
}

void sema_wait(sema_t *sema) {
  pthread_mutex_lock(&sema->mutex);
  while(sema->value <= 0)
    pthread_cond_wait(&sema->cond, &sema->mutex);
  --sema->value;
  pthread_mutex_unlock(&sema->mutex);
}

void sema_signal(sema_t *sema) {
  pthread_mutex_lock(&sema->mutex);
  ++sema->value;
  pthread_cond_signal(&sema->cond);
  pthread_mutex_unlock(&sema->mutex);
}


// 生产者
void *produce(void *arg) {
  int item, i;

  for(i = 0; i < ITEM_COUNT; i++) {
    sema_wait(&empty_buffer1_sema);
    sema_wait(&mutex1_sema);

    item = 'a' + i;
    printf("produce item: %c\n", item);
    put_item1(item);

    sema_signal(&mutex1_sema);
    sema_signal(&full_buffer1_sema);
  }
  return NULL;
}

// 计算者
void *compute(void *arg) {
  int item, i;

  for(i = 0; i < ITEM_COUNT; i++) {
    sema_wait(&full_buffer1_sema);
    sema_wait(&mutex1_sema);
    
    item = get_item1();
    printf("\t\tcompute item before: %c\n", item);
    item = item - 32;
    printf("\t\tcompute item after : %c\n", item);

    sema_signal(&mutex1_sema);
    sema_signal(&empty_buffer1_sema);

    sema_wait(&empty_buffer2_sema);
    sema_wait(&mutex2_sema);
    
    put_item2(item);

    sema_signal(&mutex2_sema);
    sema_signal(&full_buffer2_sema);
  }
  return NULL;
}

// 消费者
void *consume(void *arg) {
  int item, i;

  for(i = 0; i < ITEM_COUNT; i++) {
    sema_wait(&full_buffer2_sema);
    sema_wait(&mutex2_sema);
    
    item = get_item2();
    printf("\t\t\t\t\tconsume item: %c\n", item);

    sema_signal(&mutex2_sema);
    sema_signal(&empty_buffer2_sema);
  }
  return NULL;
}


int main() {
  pthread_t computer_tid, consumer_tid;

  sema_init(&mutex1_sema, 1);
  sema_init(&mutex2_sema, 1);
  sema_init(&empty_buffer1_sema, CAPACITY - 1);
  sema_init(&empty_buffer2_sema, CAPACITY - 1);
  sema_init(&full_buffer1_sema, 0);
  sema_init(&full_buffer2_sema, 0);

  pthread_create(&computer_tid, NULL, compute, NULL);
  pthread_create(&consumer_tid, NULL, consume, NULL);
  produce(NULL);
  pthread_join(computer_tid, NULL);
  pthread_join(consumer_tid, NULL);

  return 0;
}

4.运行结果

$ gcc pc2.c -lpthread
$ ./a.out 
produce item: a
produce item: b
produce item: c
                compute item before: a
                compute item after : A
                compute item before: b
                compute item after : B
                compute item before: c
                compute item after : C
                                        consume item: A
                                        consume item: B
                                        consume item: C
produce item: d
produce item: e
produce item: f
                compute item before: d
                compute item after : D
produce item: g
				compute item before: e
                compute item after : E
                compute item before: f
                compute item after : F
                compute item before: g
                compute item after : G
produce item: h
										consume item: D
                                        consume item: E
                                        consume item: F
                compute item before: h
                compute item after : H
                                        consume item: G
                                        consume item: H
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值