生产者-消费者模型

 
最近多次看到大家在讨论生产者-消费者模型,觉得使用信号量是最简单的,但效率上可能会有些影响,因为每次对消息的操作都要从用户态转到内核态。
什么是 生产者-消费者模型,即多个模块产生数据,另外多个模块取得数据并进行处理。如何实现互斥?如何让生产者和消费者都能够方便的工作?
本设计的主要特色为:
·消息的大小、结构是自由的,甚至可以是一个对象;
·消息队列的长度(容纳消息的个数)是可设定的;
·添加消息是阻塞的,即如果队列已满,不能再添加消息;
·代码少,思路简洁,可以根据情况扩展.
以下是该模型的实现:
template  < class  T >  
class  PCM_SEM
{
public:
    
// constructor
    PCM_SEM(int nSize)
    
{
        InitializeCriticalSection(
&m_csLock);
        _ASSERT(m_hPushSemaphore 
= CreateSemaphore(NULL, nSize, nSize, NULL));
        _ASSERT(m_hPopSemaphore 
= CreateSemaphore(NULL, 0, nSize, NULL));
    }


    
// destructor
    ~PCM_SEM()
    
{
        m_listUserData.clear();
        CloseHandle(m_hPopSemaphore);
        CloseHandle(m_hPushSemaphore);
        DeleteCriticalSection(
&m_csLock);
    }


    
// wait for the semaphore to add the msg
    void Push(T& t)
    
{
        _ASSERT(WaitForSingleObject(m_hPushSemaphore, INFINITE) 
== WAIT_OBJECT_0);
        EnterCriticalSection(
&m_csLock);
        m_listUserData.push_back(t);
        ReleaseSemaphore(m_hPopSemaphore, 
1, NULL);
        LeaveCriticalSection(
&m_csLock);
    }


    
// wait for the semaphore to get the msg
    T Pop()
    
{
        _ASSERT(WaitForSingleObject(m_hPopSemaphore, INFINITE) 
== WAIT_OBJECT_0);
        EnterCriticalSection(
&m_csLock);
        T t 
= m_listUserData.front();
        m_listUserData.pop_front();
        ReleaseSemaphore(m_hPushSemaphore, 
1, NULL);
        LeaveCriticalSection(
&m_csLock);
        
return t;
    }


private:
    CRITICAL_SECTION m_csLock; 
    HANDLE   m_hPopSemaphore;
    HANDLE   m_hPushSemaphore;
    list
<T>  m_listUserData;
}
;

下面是该模型的使用:

const   int  SIZE_BUFFER  =   100 ;

PCM_SEM
< int >  pcmData(SIZE_BUFFER);

unsigned __stdcall Producer(LPVOID lpPara)
{
    
int i = 0;
    
for ( ; ; )
    
{
        i
++;
        stringstream ss;
        ss 
<< "Produce No. " << i << " Product!" << endl;
        cout 
<< ss.str();
        pcmData.Push(i);
        Sleep(
10);
    }


    
return 0;
}


unsigned __stdcall Consumer(LPVOID lpPara)
{
    
for ( ; ; )
    
{
        stringstream ss;
        ss 
<< "Consume No. " << pcmData.Pop() << " Product!" << endl;
        cout 
<< ss.str();
        Sleep(
50);
    }


    
return 0;
}


int  main( int  argc,  char *  argv[])
{
    
if (_beginthreadex(NULL, 0&Producer, NULL, 0, NULL) == NULL) 
    
{
        
return -1;
    }


    
if (_beginthreadex(NULL, 0&Consumer, NULL, 0, NULL) == NULL) 
    
{
        
return -1;
    }


    
return getchar();
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值