信号量生产者和消费者模型

使用信号量完成线程间同步,模拟生产者,消费者问题。                                         【sem_product_consumer.c】

思路分析:

  规定: 如果□中有数据,生产者不能生产,只能阻塞。

  如果□中没有数据,消费者不能消费,只能等待数据。

  定义两个信号量:S满 = 0, S空 = 1 (S满代表满格的信号量,S空表示空格的信号量,程序起始,格子一定为空) 

-------------------------------------------------------------------------------------------------------------------------------------

  所以有:T生产者主函数 {           T消费者主函数 {

        sem_wait(S空);             sem_wait(S满);

        生产....                 消费....

        sem_post(S满);             sem_post(S空);

        }                }

-------------------------------------------------------------------------------------------------------------------------------------

假设:线程到达的顺序是:T生、T生、T消。

那么: T生1 到达,将S空-1,生产,将S满+1

   T生2 到达,S空已经为0, 阻塞

   T消 到达,将S满-1,消费,将S空+1

三个线程到达的顺序是:T生1、T生2、T消。而执行的顺序是T生1、T消、T生2

这里,S空 表示空格子的总数,代表可占用信号量的线程总数-->1。其实这样的话,信号量就等同于互斥锁。

但,如果S空=2、3、4……就不一样了,该信号量同时可以由多个线程占用,不再是互斥的形式。因此我们说信号量是互斥锁的加强版。

//信号量实现 生产者 消费者问题

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

#define NUM 5

int queue[NUM];    //全局数组实现环形队列
sem_t blank_number, product_number;    //空格子信号量

void *producer(void *arg){
    int i=0;

    while(1){
        sem_wait(&blank_number);    //生产者将空格子数--,为0则阻塞等待
        queue[i] = rand()%1000+1;    //生成一个产品
        printf("------Produce------%d\n", queue[i]);

        sem_post(&product_number);    //将产品数++

        i = (i+1)%NUM;            //借助下表实现环形
        sleep(rand()%1);
    }

}

void *consumer(void *arg){
    int i=0;

    while(1){
        sem_wait(&product_number);    //消费者将产品数--,为0则阻塞等待
        printf("------Consume------%d\n", queue[i]);
        queue[i] = 0;
        sem_post(&blank_number);    //消费一个产品

        i = (i+1)%NUM;
        sleep(rand()%3);

    }
}
int main(int argc, char *argv[]){
    pthread_t pid, cid;

    sem_init(&blank_number, 0, NUM);    //初始化空格子信号量为5
    sem_init(&product_number, 0, 0);    //产品数为0

    pthread_create(&pid, NULL, producer, NULL);
    pthread_create(&cid, NULL, consumer, NULL);

    pthread_join(pid, NULL);
    pthread_join(cid, NULL);

    sem_destroy(&blank_number);
    sem_destroy(&product_number);

    return 0;
}/*输出:

------Produce------384
------Consume------384
------Produce------916
------Produce------336
------Produce------493
------Produce------422
------Produce------28
------Consume------916
------Produce------764
------Consume------336
------Produce------427
------Consume------493
------Produce------212
------Consume------422
------Produce------430
------Consume------28
------Produce------863
------Consume------764
------Produce------136
------Consume------427
------Consume------212
------Produce------59
------Consume------430
------Consume------863
------Produce------457
------Produce------43
------Produce------374
------Consume------136
------Produce------785
------Consume------59
------Produce------325
------Consume------457
------Produce------414
------Consume------43
------Produce------981

*/

原文地址:https://www.cnblogs.com/zyqy/p/10801030.html

时间: 2024-10-08 21:52:37

信号量生产者和消费者模型的相关文章

生产者、消费者模型

转载地址:http://blog.csdn.net/snow_5288/article/details/72794306 一.概念引入 日常生活中,每当我们缺少某些生活用品时,我们都会去超市进行购买,那么,你有没有想过,你是以什么身份去的超市呢?相信大部分人都会说自己是消费者,确实如此,那么既然我们是消费者,又是谁替我们生产各种各样的商品呢?当然是超市的各大供货商,自然而然地也就成了我们的生产者.如此一来,生产者有了,消费者也有了,那么将二者联系起来的超市又该作何理解呢?诚然,它本身是作为一座交

Java线程学习整理--4---一个简单的生产者、消费者模型

 1.简单的小例子: 下面这个例子主要观察的是: 一个对象的wait()和notify()使用情况! 当一个对象调用了wait(),那么当前掌握该对象锁标记的线程,就会让出CPU的使用权,转而进入该对象的等待池中等待唤醒,这里说明一下,每一个对象都有一个独立的等待池和锁池! 等待池:上述的wait()后的线程会进入等待池中,处于下图线程声明周期(简单示意图) 中的这个状态,等待池中的线程任然具有对象的锁标记,但是处于休眠状态,不是可运行状态! 当该对象调用notify方法之后,就会在等待池中系统

并发无锁队列学习(单生产者单消费者模型)

1.引言 本文介绍单生产者单消费者模型的队列.根据写入队列的内容是定长还是变长,分为单生产者单消费者定长队列和单生产者单消费者变长队列两种.单生产者单消费者模型的队列操作过程是不需要进行加锁的.生产者通过写索引控制入队操作,消费者通过读索引控制出队列操作.二者相互之间对索引是独享,不存在竞争关系.如下图所示: 2.单生产者单消费者定长队列 这种队列要求每次入队和出队的内容是定长的,即生产者写入队列和消费者读取队列的内容大小事相同的.linux内核中的kfifo就是这种队列,提供了读和写两个索引.

Java并发协作——生产者、消费者模型

概述 对于多线程程序来说,生产者和消费者模型是非常经典的模型.更加准确的说,应该叫"生产者-消费者-仓库模型".离开了仓库,生产者.消费者就缺少了共用的存储空间,也就不存在并非协作的问题了. 示例 定义一个场景.一个仓库只允许存放10件商品,生产者每次可以向其中放入一个商品,消费者可以每次从其中取出一个商品.同时,需要注意以下4点: 1.  同一时间内只能有一个生产者生产,生产方法需要加锁synchronized. 2.  同一时间内只能有一个消费者消费,消费方法需要加锁synchro

单生产者-多消费者模型中遇到的问题

(1)      原始代码 最近使用单生产者-多消费者模型是遇到一个问题,以前既然都没有想到过.生产者线程的代码如下,基本功能就是接收到一个连接之后创建一个Socket对象并放到list中等待处理. void DataManager::InternalStart() { server_socket_ = new ServerSocket(); if (!server_socket_->SetAddress(NetworkUtil::GetIpAddress().c_str(), 9091)) {

并发协作:多线程中的生产者与消费者模型

对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的.就像学习每一门编程语言一样,Hello World!都是最经典的例子. 实际上,准确说应该是“生产者-消费者-仓储”模型,离开了仓储,生产者消费者模型就显得没有说服力了. 对于此模型,应该明确一下几点: 1.生产者仅仅在仓储未满时候生产,仓满则停止生产. 2.消费者仅仅在仓储有产品时候才能消费,仓空则等待. 3.当消费者发现仓储没产品可消费时候会通知生产者生产. 4.生产者在生产出可消费产品时候,应该通知等待的消费者去消费.

开启子进程的两种方式,孤儿进程与僵尸进程,守护进程,互斥锁,IPC机制,生产者与消费者模型

开启子进程的两种方式 # # # 方式一: # from multiprocessing import Process # import time # # def task(x): # print('%s is running' %x) # time.sleep(3) # print('%s is done' %x) # # if __name__ == '__main__': # # Process(target=task,kwargs={'x':'子进程'}) # p=Process(tar

守护进程,互斥锁,IPC,队列,生产者与消费者模型

小知识点:在子进程中不能使用input输入! 一.守护进程 守护进程表示一个进程b 守护另一个进程a 当被守护的进程结束后,那么守护进程b也跟着结束了 应用场景:之所以开子进程,是为了帮助主进程完成某个任务,然而,如果主进程认为自己的事情一旦做完了就没有必要使用子进程了,就可以将子进程设置为守护进程 例如:在运行qq的过程,开启一个进程,用于下载文件,然而文件还没有下载完毕,qq就退出了,下载任务也应该跟随qq的退出而结束. from multiprocessing import Process

Go语言编程:使用条件变量Cond和channel通道实现多个生产者和消费者模型

如题,使用条件变量Cond和channel通道实现多个生产者和消费者模型.Go语言天生带有C语言的基因,很多东西和C与很像,但是用起来 绝对比C语言方便.今天用Go语言来实现下多消费者和生产者模型.如果对C语言的多生产者和消费者模型感兴趣的可以看Linux系统编程:使用mutex互斥锁和条件变量实现多个生成者和消费者模型 代码实现代码实现用了Cond条件变量和channel通道. package main import ( "fmt" "math/rand" &qu