Fork me on GitHub

【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;
}

 

也能达到效果:

 

posted @ 2015-04-17 15:43 whatbeg 阅读(...) 评论(...) 编辑 收藏