用信號量機制解決生產者消費者問題

使用POSIX標準中的Pthreads API來建立多個生產者、消費者線程app

定義線程:pthread_t tidpost

建立線程:pthread_create(&tid,&attr,runner,argv[1]);spa

join線程:pthread_join(tid,NULL);線程

使用PthreadsAPI的信號量機制互斥與同步code

定義信號量:sem_t sem隊列

初始化信號量:sem_init(&sem, 0, n);同步

P操做:sem_wait(&sem);產品

V操做:sem_post(&sem);it

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

#define BUFF_SIZE 5 // 定義緩衝區buffer大小爲5
int buffer[BUFF_SIZE]; // 用循環隊列模擬緩衝區
int in = 0; // 產品進緩衝區時的緩衝區下標
int out = 0; // 產品出緩衝區時的緩衝區下標
int productID = 0; // 產品號
int consumeID = 0; // 將被消耗的產品號
sem_t s; // 定義互斥信號量, 互斥鎖s
sem_t n; // 定義同步信號量n, buffer中已放入的產品個數
sem_t e; // 定義同步信號量e, buffer中空單元個數

// 生產一個產品, 輸出新產品的ID號
void produce()
{
    printf("成功生產了第:%d個產品\n",++productID);
}
// 把新生產的產品放入buffer
void appen()
{
    printf("將新生產的產品放入緩衝區\n");
    buffer[in] = productID;
    in = (in+1)%BUFF_SIZE;
    int i;
    // 輸出緩衝區當前的狀態
    for(i = 0; i<BUFF_SIZE; i++)
    {
        printf("i : %d",buffer[i]);
        if(i == in) printf("<-生產");
        if(i == out) printf("<-消費");
        printf("\n");
    }
    printf("\n");
}
// 生產者
void * Producer()
{
    while(1)
    {
        sem_wait(&e); // 生產者首先試圖拿一個buffer空單元, 獲取一個空單元
        sem_wait(&s); // 獲取互斥鎖s, 對臨界區加鎖, 互斥訪問臨界區buffer
        produce(); // 生產一個產品
        appen(); // 把新生產的產品放入buffer
        Sleep(1000); // 模擬實際生產, 耗時1S
        sem_post(&s); // 臨界區buffer訪問完畢, 釋放互斥鎖s
        sem_post(&n); // 生產者任務完成, 釋放一個產品
    }
}
// 從buffer中取出一個產品
void take()
{
    printf("從緩衝區中取出第:%d個產品\n",++consumeID);
    consumeID = buffer[out];
    out = (out+1)%BUFF_SIZE;
    int i;
    // 輸出緩衝區當前的狀態
    for(i = 0; i<BUFF_SIZE; i++)
    {
        printf("i : %d",buffer[i]);
        if(i == in) printf("<-生產");
        if(i == out) printf("<-消費");
        printf("\n");
    }
}
// 消耗一個產品
void consume()
{
    printf("消費了%d個產品\n\n",consumeID);
}

// 消費者
void * Consumer()
{
    while(1)
    {
        sem_wait(&n); // 消費者首先試圖拿一個buffer產品,獲取一個產品
        sem_wait(&s); // 獲取互斥鎖s,對臨界區加鎖,互斥訪問臨界區buffer
        take(); // 從buffer中取出一個產品
        consume(); // 消耗一個產品
        Sleep(1000); // 模擬實際消費,耗時1S
        sem_post(&s); // 臨界區buffer訪問完畢,釋放互斥鎖s
        sem_post(&e); // 生產者任務完成,釋放一個buffer空單元
    }
}
int main()
{
    // 調整下面的數值,能夠發現,當生產者個數多於消費者個數時,
    // 生產速度快,生產者常常等待消費者;反之,消費者常常等待

    // 生產者的個數
    int P_COUNT = 2;
    // 消費者的個數
    int C_COUNT = 1;

    pthread_t p[P_COUNT],c[C_COUNT];
    // 建立各個信號
    sem_init(&s,0,1); // 初始化信號量s爲互斥鎖
    sem_init(&n,0,0); // 初始化信號量n:buffer中已放入的產品數目(初始爲0)
    sem_init(&e,0,BUFF_SIZE); // 初始化buffer中單元數目爲BUFF_SIZE
    int i = 0;
    // 建立生產者線程
    for(i = 0; i < P_COUNT; i++)
    {
        pthread_create(&p[i],NULL,Producer,NULL);
        pthread_create(&c[i],NULL,Consumer,NULL);
    }
    // 建立消費者線程
    for(i = 0; i < C_COUNT; i++)
    {
        pthread_join(p[i],NULL);
        pthread_join(c[i],NULL);
    }
}

Console輸出:io

成功生產了第:1個產品

將新生產的產品放入緩衝區

i : 1<-消費

i : 0<-生產

i : 0

i : 0

i : 0


成功生產了第:2個產品

將新生產的產品放入緩衝區

i : 1<-消費

i : 2

i : 0<-生產

i : 0

i : 0


成功生產了第:3個產品

將新生產的產品放入緩衝區

i : 1<-消費

i : 2

i : 3

i : 0<-生產

i : 0


從緩衝區中取出第:1個產品

i : 1

i : 2<-消費

i : 3

i : 0<-生產

i : 0

消費了1個產品


從緩衝區中取出第:2個產品

i : 1

i : 2

i : 3<-消費

i : 0<-生產

i : 0

消費了2個產品


成功生產了第:4個產品

將新生產的產品放入緩衝區

i : 1

i : 2

i : 3<-消費

i : 4

i : 0<-生產


成功生產了第:5個產品

將新生產的產品放入緩衝區

i : 1<-生產

i : 2

i : 3<-消費

i : 4

i : 5

...

...

相關文章
相關標籤/搜索