生产者-消费者模型
生產(chǎn)者-消費者模型,覺得使用信號量是最簡單的,但效率上可能會有些影響,因為每次對消息的操作都要從用戶態(tài)轉(zhuǎn)到內(nèi)核態(tài)。 什么是生產(chǎn)者-消費者模型,即多個模塊產(chǎn)生數(shù)據(jù),另外多個模塊取得數(shù)據(jù)并進行處理。如何實現(xiàn)互斥?如何讓生產(chǎn)者和消費者都能夠方便的工作? 本設計的主要特色為: ·消息的大小、結(jié)構(gòu)是自由的,甚至可以是一個對象;
·消息隊列的長度(容納消息的個數(shù))是可設定的; ·添加消息是阻塞的,即如果隊列已滿,不能再添加消息;
·代碼少,思路簡潔,可以根據(jù)情況擴展. 以下是該模型的實現(xiàn): 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;
};
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();
}
·消息隊列的長度(容納消息的個數(shù))是可設定的; ·添加消息是阻塞的,即如果隊列已滿,不能再添加消息;
·代碼少,思路簡潔,可以根據(jù)情況擴展. 以下是該模型的實現(xiàn): 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();
}
轉(zhuǎn)載于:https://www.cnblogs.com/Coterjiesen/p/4900519.html
總結(jié)
- 上一篇: 有向无环图的拓扑排序
- 下一篇: jvisualvm远程监控Tomcat