Linux多线程实现生产者-消费者模型:代码示例与解析

本篇文章将通过代码示例演示使用Linux下的pthread库实现经典的生产者-消费者问题,并详细解释代码中的互斥锁和条件变量的使用。

代码示例

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

#define BUFFER_SIZE 5  // 缓冲区大小

int buffer[BUFFER_SIZE];  // 缓冲区数组
int count = 0;  // 缓冲区中的数据个数

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

void* producer(void* arg) {
    int num = *(int*)arg;
    free(arg);

    for (int i = 1; i <= 10; i++) {
        pthread_mutex_lock(&mutex);

        while (count == BUFFER_SIZE) {
            // 缓冲区满,等待消费者消费
            pthread_cond_wait(&full, &mutex);
        }

        buffer[count++] = i;
        printf('Producer %d: produced item %d\n', num, i);

        // 唤醒等待的消费者
        pthread_cond_signal(&empty);
        pthread_mutex_unlock(&mutex);
    }

    pthread_exit(NULL);
}

void* consumer(void* arg) {
    int num = *(int*)arg;
    free(arg);

    for (int i = 1; i <= 10; i++) {
        pthread_mutex_lock(&mutex);

        while (count == 0) {
            // 缓冲区空,等待生产者生产
            pthread_cond_wait(&empty, &mutex);
        }

        int item = buffer[--count];
        printf('Consumer %d: consumed item %d\n', num, item);

        // 唤醒等待的生产者
        pthread_cond_signal(&full);
        pthread_mutex_unlock(&mutex);
    }

    pthread_exit(NULL);
}

int main() {
    pthread_t producer_threads[2];
    pthread_t consumer_threads[2];

    // 创建生产者线程
    for (int i = 0; i < 2; i++) {
        int* arg = malloc(sizeof(int));
        *arg = i + 1;
        pthread_create(&producer_threads[i], NULL, producer, arg);
    }

    // 创建消费者线程
    for (int i = 0; i < 2; i++) {
        int* arg = malloc(sizeof(int));
        *arg = i + 1;
        pthread_create(&consumer_threads[i], NULL, consumer, arg);
    }

    // 等待所有线程完成
    for (int i = 0; i < 2; i++) {
        pthread_join(producer_threads[i], NULL);
        pthread_join(consumer_threads[i], NULL);
    }

    return 0;
}

代码解释

该代码实现了一个生产者-消费者模型,其中包含以下关键部分:

  • 缓冲区: 使用buffer数组存储生产者生产的数据,count变量记录缓冲区中当前数据个数。
  • 互斥锁: 使用pthread_mutex_t类型的mutex变量来保证对缓冲区的访问是互斥的。
  • 条件变量: 使用pthread_cond_t类型的fullempty变量分别表示缓冲区满和缓冲区空两种条件。

生产者线程:

  1. 获取互斥锁。
  2. 如果缓冲区已满,则调用pthread_cond_wait(&full, &mutex),阻塞等待条件变量full,直到有消费者取走数据。
  3. 将数据写入缓冲区。
  4. 唤醒等待的消费者线程,调用pthread_cond_signal(&empty)
  5. 释放互斥锁。

消费者线程:

  1. 获取互斥锁。
  2. 如果缓冲区为空,则调用pthread_cond_wait(&empty, &mutex),阻塞等待条件变量empty,直到有生产者放入数据。
  3. 从缓冲区取出数据。
  4. 唤醒等待的生产者线程,调用pthread_cond_signal(&full)
  5. 释放互斥锁。

代码中的要点

  • 该代码创建了两个生产者线程和两个消费者线程,每个生产者线程会依次生产数字1到10,每个消费者线程会依次取出缓冲区中的数据。
  • 为了保证线程安全,对缓冲区的所有操作都需要在互斥锁的保护下进行。
  • 使用条件变量可以有效地解决生产者和消费者之间的数据同步问题,避免出现资源争夺和死锁情况。

总结

本篇文章通过代码示例演示了如何使用Linux下的pthread库实现生产者-消费者模型,并解释了代码中互斥锁和条件变量的具体用法。该代码示例可以帮助读者更好地理解线程同步的概念,并为开发多线程应用程序提供一些实践经验。

Linux多线程实现生产者-消费者模型:代码示例与解析

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

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