文档章节

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

w
 wall--e
发布于 2016/04/17 14:59
字数 1076
阅读 708
收藏 0

使用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

...

...

© 著作权归作者所有

w
粉丝 7
博文 31
码字总数 25016
作品 0
东城
程序员
私信 提问
Linux系统中的信号量机制

1、信号量的定义: 在linux中,信号量用上述结构体表示,我们可以通过该结构体定义一个信号量。 2、信号量的初始化: 可用void sema_init(struct semaphore *sem, int val);直接创建,其中v...

宅蓝三木
2014/04/24
0
0
秒杀多线程第十篇 生产者消费者问题

继经典线程同步问题之后,我们来看看生产者消费者问题及读者写者问题。生产者消费者问题是一个著名的线程同步问题,该问题描述如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去...

长平狐
2012/12/10
56
0
秒杀多线程第十篇 生产者消费者问题

继经典线程同步问题之后,我们来看看生产者消费者问题及读者写者问题。生产者消费者问题是一个著名的线程同步问题,该问题描述如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去...

晨曦之光
2012/05/21
119
0
Python线程同步机制: Locks, RLocks, Semaphores, Condition

翻译自Laurent Luce的博客 原文名称:Python threads synchronization: Locks, RLocks, Semaphores, Conditions, Events and Queues 原文连接:http://www.laurentluce.com/posts/python-thr......

好铁
2016/03/25
37
0
操作系统--信号量的机制与应用

资源互斥访问图例 同步机制应遵循的准则 (1)空闲让进 当无进程处于临界区时,应允许一个请求进入临界区的进程进入临界区; (2)忙则等待 当已有进程进入临界区时,其他试图进入临界区的进...

yf289178199
2018/05/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

抽象同步队列AQS——AbstractQueuedSynchronizer锁详解

AQS——锁的底层支持 谈到并发,不得不谈ReentrantLock;而谈到ReentrantLock,不得不谈AbstractQueuedSynchronizer(AQS)! 类如其名,抽象的队列式的同步器,AQS定义了一套多线程访问共享资...

须臾之余
今天
2
0
springboot配置百度UEditor 富文本详解

富文本简介 UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码... 准备工作 ueditor需要单独文...

wotrd
昨天
3
0
mysql 5.7之my.cnf配置大全

[client]port = 3306socket = /tmp/mysql.sock[mysqld]###############################基础设置######################################Mysql服务的唯一编号 每个mysql服务...

Online_Reus
昨天
2
0
MAVEN打包时引入外部链接的包

1.项目引入了ORACLE的jar包,MAVEN配置如下 2.打jar包的时候需要指定下main入口函数mainClass <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc6</artifactId> ......

Cobbage
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部