zoukankan      html  css  js  c++  java
  • 生产者-消费者模型

    生产者-消费者模型,觉得使用信号量是最简单的,但效率上可能会有些影响,因为每次对消息的操作都要从用户态转到内核态。
    什么是生产者-消费者模型,即多个模块产生数据,另外多个模块取得数据并进行处理。如何实现互斥?如何让生产者和消费者都能够方便的工作?
    本设计的主要特色为:
    ·消息的大小、结构是自由的,甚至可以是一个对象;
    ·消息队列的长度(容纳消息的个数)是可设定的;
    ·添加消息是阻塞的,即如果队列已满,不能再添加消息;
    ·代码少,思路简洁,可以根据情况扩展.
     
    以下是该模型的实现:
    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();
    }
  • 相关阅读:
    Keepalived安装使用详解
    Django缓存使用方法
    Django常用命令及参数配置(Django 1.8.6)
    Python之Rpyc模块
    Hadoop:实战Web日志分析
    Hadoop:使用Mrjob框架编写MapReduce
    Hadoop:使用原生python编写MapReduce
    Hadoop安装
    LGOJP1850 换教室
    BZOJ4318: OSU!
  • 原文地址:https://www.cnblogs.com/Coterjiesen/p/4900519.html
Copyright © 2011-2022 走看看