多线程|pc1.c 使用条件变量解决生产者、计算者、消费者问题

本文介绍了如何使用条件变量解决生产者、计算者和消费者问题。系统中包含3个线程,即生产者、计算者和消费者,以及2个容量为4的缓冲区。生产者生成字符放入buffer1,计算者将小写字符转为大写存入buffer2,消费者从buffer2取出并打印。通过互斥锁和条件变量,实现了线程间的同步与通信,确保了数据的一致性和正确性。
摘要由CSDN通过智能技术生成

1.题目要求

使用条件变量解决生产者、计算者、消费者问题

  • 系统中有3个线程:生产者、计算者、消费者
  • 系统中有2个容量为4的缓冲区:buffer1、buffer2
  • 生产者生产’a’、‘b’、‘c’、‘d’、‘e’、‘f’、‘g’、'h’八个字符,放入到buffer1
  • 计算者从buffer1取出字符,将小写字符转换为大写字符,放入到buffer2
  • 消费者从buffer2取出字符,将其打印到屏幕上

2.解决思路

​ 设置两个大小为4的共享缓冲区buffer1buffer2,第一个为生产者和计算者共享,第二个为计算者和消费者共享。首先对两个共享缓冲区分别实现判断缓冲区为空、判断缓冲区为满、读取一个数据、写入一个数据的基本操作子函数:定义变量out为共享缓冲区的读指针,变量in为共享缓冲区的写指针,in指针和out指针相同时,缓冲区为空;in指针和out指针相邻时,缓冲区为满。get_item获取out指针指向的元素,同时,移动out指针指向下一项;put_item将元素放置在in指针指向的位置,同时,移动in指针指向下一项。

生产者、计算者、消费者线程的逻辑如下:

  • 生产者线程生产字符,当缓冲区被写满时,将生产者线程挂起,等待缓冲区buffer1有空闲存储空间的时候再唤醒生产者线程,将字符写入共享缓冲区buffer1中,并移动写指针,唤醒计算者线程。
  • 计算者线程从buffer1中读取数据,并移动读指针,并将读取的数据写入buffer2中,并移动写指针,当buffer1有空闲时,唤醒生产者进程,当buffer2被写满时唤醒消费者进程。
  • 消费者进程从buffer2中读取字符并输出,并移动读指针,当buffer2有空闲的时候,唤醒计算者进程。

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;
pthread_mutex_t mutex1, mutex2;
pthread_cond_t wait_empty_buffer1, wait_empty_buffer2;
pthread_cond_t wait_full_buffer1, wait_full_buffer2;


// 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;
}


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

  for(i = 0; i < ITEM_COUNT; i++) {
    pthread_mutex_lock(&mutex1);
    while(buffer1_is_full())
      pthread_cond_wait(&wait_empty_buffer1, &mutex1);

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

    pthread_cond_signal(&wait_full_buffer1);
    pthread_mutex_unlock(&mutex1);
  }
  return NULL;
}

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

  for(i = 0; i < ITEM_COUNT; i++) {
    pthread_mutex_lock(&mutex1);
    while(buffer1_is_empty())
      pthread_cond_wait(&wait_full_buffer1, &mutex1);
    
    item = get_item1();
    item = item - 32;
    printf("\t\tcompute item: %c\n", item);

    pthread_cond_signal(&wait_empty_buffer1);
    pthread_mutex_unlock(&mutex1);

    pthread_mutex_lock(&mutex2);
    while(buffer2_is_full())
      pthread_cond_wait(&wait_empty_buffer2, &mutex2);
    
    put_item2(item);

    pthread_cond_signal(&wait_full_buffer2);
    pthread_mutex_unlock(&mutex2);
  }
  return NULL;
}

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

  for(i = 0; i < ITEM_COUNT; i++) {
    pthread_mutex_lock(&mutex2);
    while(buffer2_is_empty())
      pthread_cond_wait(&wait_full_buffer2, &mutex2);
    
    item = get_item2();
    printf("\t\t\t\tconsume item: %c\n", item);

    pthread_cond_signal(&wait_empty_buffer2);
    pthread_mutex_unlock(&mutex2);
  }
  return NULL;
}


int main() {
  pthread_t computer_tid, consumer_tid;

  pthread_mutex_init(&mutex1, NULL);
  pthread_mutex_init(&mutex2, NULL);
  pthread_cond_init(&wait_empty_buffer1, NULL);
  pthread_cond_init(&wait_empty_buffer2, NULL);
  pthread_cond_init(&wait_full_buffer1, NULL);
  pthread_cond_init(&wait_full_buffer2, NULL);

  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 pc1.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
produce item: d
produce item: e
										consume item: A
                compute item before: c
                compute item after : C
                compute item before: d
                compute item after : D
                compute item before: e
                compute item after : E
produce item: f
produce item: g
produce item: h
                                        consume item: B
                                        consume item: C
                                        consume item: D
                compute item before: f
                compute item after : F
                compute item before: g
                compute item after : G
                compute item before: h
                compute item after : H
                                        consume item: E
                                        consume item: F
                                        consume item: G
                                        consume item: H
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值