以下是一个基于生产者消费者问题的C程序,使用了线程和互斥锁来实现并发编程:

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

#define BUFFER_SIZE 10 // 缓冲区大小
#define PRODUCER_NUM 3 // 生产者数量
#define CONSUMER_NUM 2 // 消费者数量

int buffer[BUFFER_SIZE]; // 缓冲区
int in = 0; // 生产者将数据写入缓冲区的位置
int out = 0; // 消费者从缓冲区读取数据的位置

pthread_mutex_t mutex; // 互斥锁
pthread_cond_t full; // 缓冲区满条件变量
pthread_cond_t empty; // 缓冲区空条件变量

void *producer(void *arg) {
    int id = *(int *)arg;
    while (1) {
        int item = rand() % 100; // 生成一个随机数作为生产的数据
        pthread_mutex_lock(&mutex); // 加锁
        while ((in + 1) % BUFFER_SIZE == out) { // 缓冲区已满,等待消费者消费
            printf("Producer %d: buffer is full, waiting for consumer...\n", id);
            pthread_cond_wait(&full, &mutex);
        }
        buffer[in] = item; // 将数据写入缓冲区
        printf("Producer %d: produce item %d\n", id, item);
        in = (in + 1) % BUFFER_SIZE; // 更新写入位置
        pthread_cond_signal(&empty); // 发送缓冲区非空信号给消费者
        pthread_mutex_unlock(&mutex); // 解锁
    }
}

void *consumer(void *arg) {
    int id = *(int *)arg;
    while (1) {
        pthread_mutex_lock(&mutex); // 加锁
        while (in == out) { // 缓冲区为空,等待生产者生产
            printf("Consumer %d: buffer is empty, waiting for producer...\n", id);
            pthread_cond_wait(&empty, &mutex);
        }
        int item = buffer[out]; // 从缓冲区读取数据
        printf("Consumer %d: consume item %d\n", id, item);
        out = (out + 1) % BUFFER_SIZE; // 更新读取位置
        pthread_cond_signal(&full); // 发送缓冲区非满信号给生产者
        pthread_mutex_unlock(&mutex); // 解锁
    }
}

int main() {
    pthread_t producers[PRODUCER_NUM];
    pthread_t consumers[CONSUMER_NUM];
    int producer_ids[PRODUCER_NUM];
    int consumer_ids[CONSUMER_NUM];
    int i;

    // 初始化互斥锁和条件变量
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&full, NULL);
    pthread_cond_init(&empty, NULL);

    // 创建生产者线程
    for (i = 0; i < PRODUCER_NUM; i++) {
        producer_ids[i] = i + 1;
        pthread_create(&producers[i], NULL, producer, &producer_ids[i]);
    }

    // 创建消费者线程
    for (i = 0; i < CONSUMER_NUM; i++) {
        consumer_ids[i] = i + 1;
        pthread_create(&consumers[i], NULL, consumer, &consumer_ids[i]);
    }

    // 等待线程结束
    for (i = 0; i < PRODUCER_NUM; i++) {
        pthread_join(producers[i], NULL);
    }
    for (i = 0; i < CONSUMER_NUM; i++) {
        pthread_join(consumers[i], NULL);
    }

    // 销毁互斥锁和条件变量
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&full);
    pthread_cond_destroy(&empty);

    return 0;
}

在该程序中,生产者线程和消费者线程都是无限循环,不断地进行生产和消费。生产者线程生成一个随机数作为生产的数据,然后将数据写入缓冲区中。如果缓冲区已满,生产者线程会等待消费者线程消费数据,直到缓冲区非满。消费者线程从缓冲区中读取数据,如果缓冲区为空,消费者线程会等待生产者线程生产数据,直到缓冲区非空。

在生产者线程和消费者线程之间,使用了互斥锁来保证缓冲区的互斥访问。当一个线程持有互斥锁时,另一个线程必须等待该锁被释放才能访问共享资源。此外,还使用了条件变量来实现线程之间的同步。当一个线程等待某个条件变量时,它会释放互斥锁,并等待条件变量被另一个线程发送信号。当另一个线程发送信号时,等待的线程会重新获得互斥锁,并继续执行。

最后,需要注意的是,在生产者消费者问题中,使用互斥锁和条件变量时需要注意避免死锁和饥饿等问题。例如,如果一个线程持有互斥锁并等待条件变量时,另一个线程也需要获得该锁才能访问共享资源,但如果该锁一直被第一个线程持有,第二个线程就会一直等待,导致饥饿问题。因此,在编写生产者消费者问题的程序时,需要仔细考虑线程之间的交互和同步方式,以确保程序的正确性和效率。

基于生产者消费者问题用C 实现并发编程

原文地址: https://www.cveoy.top/t/topic/b5TJ 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录