【Windows】用信号量实现生产者-消费者模型

线程并发的生产者-消费者模型:

1.两个进程对同一个内存资源进行操作,一个是生产者,一个是消费者。

2.生产者往共享内存资源填充数据,如果区域满,则等待消费者消费数据。

3.消费者从共享内存资源取数据,如果区域空,则等待生产者填充数据。

4.生产者的填充数据行为和消费者的消费数据行为不可在同一时间发生。

下面用Windows的信号量以及线程等API模拟生产者-消费者模型

#include <Windows.h>
#include <stdio.h>
#define N 100
#define TRUE 1
typedef int Semaphore;
Semaphore full = 0, Empty = N;            //共享资源区满槽数目和空槽数目
int in = 0, out = 0;                      //缓冲区生产,消费数据指针
HANDLE mutex;
int ProducerThread[5];
int ConsumerThread[5];
int Buffer[N+4];                          //缓冲区

int produce_item() {                      //生产(随机数)
    return (rand()%N + N)%N;
}

int insert_item(int item) {               //插入资源
    in %= N;
    printf("生产到缓冲区槽: %d\n",in);
    Buffer[in] = item;
    return Buffer[in++];
}

int remove_item() {                        //移出资源
    out %= N;
    printf("                       取走缓冲区槽 %d 的数\n",out);
    return Buffer[out++];
}

int consume_item(int item) {
    //consume it
}

void down(HANDLE handle) {                  //wait / P
    WaitForSingleObject(handle, INFINITE);
}

void up(HANDLE handle) {                    //signal / V
    ReleaseSemaphore(handle, 1, NULL);
}

DWORD WINAPI producer(LPVOID v) {

    int item;

    while(TRUE) {

        item = produce_item();
        if(Empty > 0) {           //down(empty)
            Empty--;
            down(mutex);          //down(mutex)
            insert_item(item);
            full++;               //up(full)
            up(mutex);            //up(mutex)
        }

        Sleep(2000);
    }
    return 1;
}

DWORD WINAPI consumer(LPVOID v) {

    int item;

    while(TRUE) {

        if(full > 0) {             //down(full)
            full--;
            down(mutex);           //down(mutex)
            item = remove_item();
            consume_item(item);
            Empty++;               //up(empty)
            up(mutex);             //up(mutex)
        }

        Sleep(2000);
    }
    return 1;
}

int main()
{
    DWORD Tid;

    mutex = CreateSemaphore(             //创建互斥信号量mutex
            NULL,
            1,
            1,
            NULL
        );

    for(int i=0;i<4;i++) {
        ProducerThread[i] = i+1;
        CreateThread(                    //创建生产者线程
            NULL,                        //不能被子线程继承
            0,                           //默认堆栈大小
            producer,                    //生产者函数
            &ProducerThread[i],          //传参
            0,                           //创建后立即执行
            &Tid                         //线程ID
        );
        ConsumerThread[i] = i+1;
        CreateThread(NULL,0,consumer,&ConsumerThread[i],0,&Tid);   //创建消费者线程
    }

    Sleep(20000);
    return 0;
}

运行结果:

或者使用自定义的信号量mutex来实现:

#include <Windows.h>
#include <stdio.h>
#define N 100
#define TRUE 1
typedef int Semaphore;
Semaphore mutex = 1;           //互斥信号量
Semaphore full = 0, Empty = N; //临界区满槽数目和空槽数目
int in = 0, out = 0;           //缓冲区生产,消费数据指针
int ProducerThread[5];
int ConsumerThread[5];
int Buffer[N+4];               //缓冲区

int produce_item() {           //生产随机数
    return (rand()%N + N)%N;
}

int insert_item(int item) {    //插入临界区
    in %= N;
    printf("生产到缓冲区槽: %d\n",in);
    Buffer[in] = item;
    return Buffer[in++];
}

int remove_item() {            //移出临界区
    out %= N;
    printf("                        取走缓冲区槽 %d 的数\n",out);
    return Buffer[out++];
}

int consume_item(int item) {
    //consume it
}

DWORD WINAPI producer(LPVOID v) {

    int item;

    while(TRUE) {

        item = produce_item();     //生产物品
        Empty--;                   //P(Empty)
        if(Empty < 0)              //没有空槽可以添加数据
            Empty++;               //还原Empty,继续循环等待
        else if(mutex > 0) {       //否则如果mutex = 1,临界区未被访问
            mutex--;               //加锁
            insert_item(item);     //往临界区填入数据
            full++;                //满槽数加1
            mutex++;               //释放锁
        }
        Sleep(2000);
    }
    return 1;
}

DWORD WINAPI consumer(LPVOID v) {

    int item;

    while(TRUE) {

        full--;                   //P(full)
        if(full < 0)              //如果没有满槽,无法消费
            full++;               //还原full,继续等待
        else if(mutex > 0) {      //否则如果mutex = 1,临界区未被访问
            mutex--;              //加锁
            item = remove_item(); //将数据移出临界区
            consume_item(item);   //消费
            Empty++;              //空槽数目加1
            mutex++;              //释放锁
        }

        Sleep(2000);
    }
    return 1;
}

int main()
{
    DWORD Tid;

    for(int i=0;i<4;i++) {
        ProducerThread[i] = i+1;
        CreateThread(NULL,0,producer,0,0,&Tid);
        ConsumerThread[i] = i+1;
        CreateThread(NULL,0,consumer,0,0,&Tid);
    }

    Sleep(20000);
    return 0;
}

也能达到效果:

时间: 2024-07-30 17:44:05

【Windows】用信号量实现生产者-消费者模型的相关文章

基于POSIX的信号量的生产者消费者模型

信号量和Mutex类似,表示可用资源的数量,和Mutex不同的是,这个数量可以大于1,即如果信号量描述的资源数目是1时,此时的信号量和互斥锁相同. 下面我们看看POSIX semaphore库函数,它既可以用于同一进程的线程间同步,也可以用于不同进程间的同步. 1. int sem_init(sem_t *sem,int pshared,unsigned int value) 我们可以用此函数来创建一个未命名的信号量,pshared参数表明是否在多个进程中使用信号量,如果是,将其设置为非0 值,

13 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件  queue队列 生产者消费者模型 Queue队列 开发一个线程池

本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者消费者模型 Queue队列 开发一个线程池 进程 语法 进程间通讯 进程池 操作系统发展史 手工操作(无操作系统) 1946年第一台计算机诞生--20世纪50年代中期,还未出现操作系统,计算机工作采用手工操作方式. 手工操作程序员将对应于程序和数据的已穿孔的纸带(或卡片)装入输入机,然后启动输入机把

Python之路(第三十八篇) 并发编程:进程同步锁/互斥锁、信号量、事件、队列、生产者消费者模型

一.进程锁(同步锁/互斥锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理. 例子 #并发运行,效率高,但竞争同一打印终端,带来了打印错乱 from multiprocessing import Process import os,time def work(): print('%s is running' %os.getpid()) time.sleep(2) print('

python2.0_s12_day9之day8遗留知识(queue队列&amp;生产者消费者模型)

4.线程 1.语法 2.join 3.线程锁之Lock\Rlock\信号量 4.将线程变为守护进程 5.Event事件 * 6.queue队列 * 7.生产者消费者模型 4.6 queue队列 queue非常有用,当信息必须安全的在多个线程之间进行数据交换的时候就应该想到queue 所以,queue它能保证数据被安全的在多个线程之间进行交换,那他就是天生的线程安全. queue有那么几种: class queue.Queue(maxsize=0) # 先入先出 class queue.LifoQ

OpenMP实现生产者消费者模型

生产者消费者模型已经很古老了吧,最近写了个OpenMP版的此模型之实现,来分享下. 先说一下模型的大致做法是: 1.生产者需要取任务,生产产品. 2.消费者需要取产品,消费产品. 生产者在生产某个产品之后,要告知消费者此产品已经可以使用了.消费者通过获得可以使用这个信号来取得产品,进一步消费产品. 比如,我们有N个图像需要对每一个图像作滤波或者变换等处理,并且把处理后的结果存到硬盘上. 那么生产者可以将N个图像看成N个任务,每个任务都是独立的,每个任务的计算结果可以看成是产品,消费者就是取这个产

Python学习笔记——进阶篇【第九周】———线程、进程、协程篇(队列Queue和生产者消费者模型)

Python之路,进程.线程.协程篇 本节内容 进程.与线程区别 cpu运行原理 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者消费者模型 Queue队列 开发一个线程池 进程 语法 进程间通讯 进程池 参考链接http://www.cnblogs.com/alex3714/articles/5230609.html

进击的Python【第九章】:paramiko模块、线程与进程、各种线程锁、queue队列、生产者消费者模型

一.paramiko模块 他是什么东西? paramiko模块是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接. 先来个实例: 1 import paramiko 2 # 创建SSH对象 3 ssh = paramiko.SSHClient() 4 5 # 允许连接不在know_hosts文件中的主机 6 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 7 # 连接服务器 8 ss

生产者消费者模型中线程怎样正常退出

生产者:不停地往队列中放数据 消费者:不停地从队列中拿数据 两者通过两个信号量同步 当生产者不再生产数据时,消费者正好挂在一个信号量上,处于睡眠状态,这时候pthread_join也会一直挂着的.该怎样使得消费者正常退出呢? 我的做法是让生产者在往队列中放一个[结束数据],也就是一个标识,消费者拿到数据后,如果这个数据是结束标识则自杀退出. 生产者消费者模型中线程怎样正常退出

浅谈生产者消费者模型与读写者模型的区别

多线程编程在操作系统中是十分重要的. 而在线程中处理同步与互斥问题又是至关重要的.生产者-消费者模型,(也称有限缓冲问题)是一个多线程同步问题的经典例子.下来我们对其进行简单分析. 生产者-->生成一定量的数据放到缓冲区中,然后重复此过程: 消费者-->在缓冲区消耗这些数据. 而生产者-消费者之间存在三种关系,即 生产者与生产者之间是互斥关系: 消费者与消费者之间是互斥关系: 生产者与消费者之间是同步与互斥关系. 下面的程序演示了一个生产者-消费者的例子,生产者生产一个结构体串在链表的表头上,