信号量实现生产者消费者模型

一、信号量

信号量是进化版的互斥锁,由于互斥锁的粒度比较大,如果我们希望在多个线程间对某一对象的部分数据进行共享,使用互斥锁是没有办法实现的,只能将整个数据对象锁住,这样虽然达到了多线程操作共享数据正确性的目的,却无形中导致线程的并发性下降。线程从并行执行,变成了串行执行。与直接使用单进程无异。而信号量是相对折中的一种处理方式,既能保证同步,数据不混乱又能提高线程的并发。

二、主要应用函数

sem_t sem; 定义信号量
int sem_init(sem_t *sem, int pshared, unsigned int value);
参数:
	sem: 信号量
	pshared: 0: 用于线程间同步
	  		  1: 用于进程间同步
	value:N 值(指定同时访问的线程数)	

int sem_destroy(sem_t *sem);

int sem_wait(sem_t *sem); 
int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
	 一次调用,做一次-- 操作,当信号量的值为 0 时,再次 -- 就会阻塞。
	(对比 pthread_mutex_lock()int sem_post(sem_t *sem);
	一次调用,做一次++ 操作
   (对比 pthread_mutex_unlock())
   
返回值: 均是成功:0	失败:-1,errno被设置

三、生产者消费者模型

开发流程图示:

在这里插入图片描述

需要注意的是:使用信号量实现生产者消费者模型,对于生产过程消费过程并不是原子操作,单一生产者、消费者没什么问题,但是多生产者、消费者情况下,生产过程或消费过程过于耗时,不能保证不会出现生产冲突消费冲突的后果。

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <semaphore.h>

#define MAX     5

sem_t sem_pro;	//产品
sem_t sem_sto;	//容量
int queue[MAX];
int i, j;

void *producer(void* arg)
{
        while (1) {
                sem_wait(&sem_sto);	//容量--,容量为0则阻塞等待

                queue[j] = rand()%200 + 1;	//生产产品
                printf("%lu:Produce a product:%d\n", pthread_self(), queue[j]);

                sem_post(&sem_pro);	//产品数++

                j = (j+1) % MAX;	//借助下标实现环形队列
                sleep(rand() % 3);
        }

        pthread_exit(NULL);
}

void *consumer(void *arg)
{
        while (1) {
                sem_wait(&sem_pro);	//产品--,产品为0则阻塞等待

                printf("        %lu:Consume a product:%d\n", pthread_self(), queue[i]);
                queue[i] = 0;	//消费产品

                sem_post(&sem_sto);	//容量++

                i = (i+1) % MAX;	//借助下标实现环形队列
                sleep(rand()%3);
        }

        pthread_exit(NULL);
}


int main()
{
        int ret;
        pthread_t producerID;
        pthread_t consumerID;

        srand(time(NULL));
        sem_init(&sem_pro, 0, 0);
        sem_init(&sem_sto, 0, MAX);
        ret = pthread_create(&producerID, NULL, producer, NULL);
        if (ret != 0) {
                fprintf(stderr, "pthread_create:producer error  ret:%s\n", strerror(ret));
                exit(-1);
        }
        ret = pthread_create(&consumerID, NULL, consumer, NULL);
        if (ret != 0) {
                fprintf(stderr, "pthread_create:consumer error  ret:%s\n", strerror(ret));
                exit(-1);
        }

        pthread_join(producerID, NULL);
        pthread_join(consumerID, NULL);
        sem_destroy(&sem_pro);
        sem_destroy(&sem_sto);

        return 0;
}

运行结果:

140011622741760:Produce a product:164
	140011614349056:Consume a product:164
140011622741760:Produce a product:10
	140011614349056:Consume a product:10
140011622741760:Produce a product:137
140011622741760:Produce a product:167
140011622741760:Produce a product:118
	140011614349056:Consume a product:137
	140011614349056:Consume a product:167
140011622741760:Produce a product:43
	140011614349056:Consume a product:118
	140011614349056:Consume a product:43
140011622741760:Produce a product:21
	140011614349056:Consume a product:21
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值