生產者-消費者的問題

生產者-消費者問題是最經典的操作系統同步與互斥相結合的問題。生活中的很多問題,要麼是它的變形,要麼是它的簡化。

本篇博客的實現方法是用linux版本的線程互斥鎖+線程信號量來實現該問題。

問題場景:m個生產者,n個消費者,大小爲k的緩衝區。

1、互斥保證:對緩衝區的操作是互斥的。用互斥鎖(pthread_mutex_t)實現。
2、同步保證:當緩衝區爲空時,消費者阻塞;當緩衝區爲滿時,生產者阻塞。用線程信號量(sem_t)實現。

編程細節:
1、信號量的初始化:緩衝區初始爲空,因此生產者的初始信號量值爲k,消費者的初始信號量值爲0.
2、先獲取互斥鎖,然後才能獲取信號量。否則會造成死鎖。
3、生產者、消費者分別需要一個變量idx來記錄可以當前自己可處理的位置。
#include <stdio.h>
#include <pthread.h> //多線程、互斥鎖所需頭文件
#include <semaphore.h> //線程信號量所需頭文件

//設置生產者、消費者、緩衝區的個數
#define M 10
#define N 10
#define K 10
#define X 10

//互斥鎖
pthread_mutex_t mutex;
//信號量
sem_t pro;
sem_t con;

//緩衝區和生產者、消費者的遊標
int buffer[K] = {0};
int pro_idx = 0;
int con_idx = 0;

void *producer(void *)
{
    for(int i=0;i<X;i++)
    {
        sem_wait(&pro);
        pthread_mutex_lock(&mutex);
        
        int tmp = buffer[pro_idx];
        printf("Produce at buffer[%d] : from %d to 1\n", pro_idx, tmp);
        buffer[pro_idx] = 1;
        pro_idx = (pro_idx+1) % K;
    
        pthread_mutex_unlock(&mutex);
        sem_post(&con);
    }
    return NULL;
}

void *consumer(void *)
{
    for(int i=0;i<X;i++)
    {
        sem_wait(&con);
        pthread_mutex_lock(&mutex);
    
        int tmp = buffer[con_idx];
        printf("Consumer at buffer[%d] : from %d to 0\n", con_idx, tmp);
        buffer[con_idx] = 0;
        con_idx = (con_idx+1) % K;
    
        pthread_mutex_unlock(&mutex);
        sem_post(&pro);
    }
    return NULL;
}

int main(int argc, const char * argv[])
{
    //聲明線程標識符
    pthread_t producer_thread[M];
    pthread_t consumer_thread[N];
    
    //初始化線程信號量:初始時爲緩衝區全空
    sem_init(&pro, 0, K);
    sem_init(&con, 0, 0);
    
    //初始化互斥鎖:下面初始化兩種方式都可以
    mutex = PTHREAD_MUTEX_INITIALIZER;
    //pthread_mutex_init(&mutex, NULL);
    
    for (int i=0; i<M; i++)
    {
        if (pthread_create(&producer_thread[i], NULL, producer, NULL))
            printf("Producer Thread Cannot Created.\n");
    }
    
    for(int i=0;i<N;i++)
    {
        if(pthread_create(&consumer_thread[i], NULL, consumer, NULL))
            printf("Consumer Thread Cannot Created.\n");
    }
    
    for(int i=0;i<M;i++)
        pthread_join(producer_thread[i], NULL);
    for(int i=0;i<N;i++)
        pthread_join(consumer_thread[i], NULL);
    
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章