用信号量机制解决生产者消费者问题

使用POSIX标准中的Pthreads API来创建多个生产者、消费者线程

定义线程:pthread_t tid

创建线程:pthread_create(&tid,&attr,runner,argv[1]);

join线程:pthread_join(tid,NULL);

使用PthreadsAPI的信号量机制互斥与同步

定义信号量:sem_t sem

初始化信号量:sem_init(&sem, 0, n);

P操作:sem_wait(&sem);

V操作:sem_post(&sem);

#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输出:

成功生产了第: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

...

...

你可能感兴趣的:(linux,api,操作系统,OS,pthreads,生产者消费者问题,互斥与同步,信号量机制)