前幾天讀了一篇文章,介紹線程同步的。講到但生產者多消費者的時候,運用了一個例子文章的博客地址:
http://blog.csdn.net/morewindows/article/details/7577591
我個人不是很理解,當一個讀線程和兩個寫線程同時使用一個臨界區時,多緩衝區的作用從何而來。個人認爲多緩衝區絕對不可以對線程進行加鎖,尤其是互斥鎖Mutex
和CriticalSection。鎖還是要加,我認爲應該加到緩衝區上,如果你有十個緩衝區,那麼你就給這個工程陪十個鎖。每個緩衝區一個,但是絕不相同。緩衝區要設計成類
讀和寫分別加鎖。這樣無論多少個消費者,都可以拿數據。消費者可以任意增加!
我的水平有限,以上只是我的意見,我並不能確定一定對。希望高人指教
</pre><pre name="code" class="html">// MutiThreadBuffer.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
//1生產者 2消費者 4緩衝區
#include <stdio.h>
#include <process.h>
#include <windows.h>
//設置控制檯輸出顏色
#include "LockFreeRingQueue.h"
const int END_PRODUCE_NUMBER = 100; //生產產品個數
const int BUFFER_SIZE = 4; //緩衝區個數
CLockFreeRingQueue oCLockFreeRingQueue(BUFFER_SIZE);
HANDLE g_hSemaphoreBufferEmpty, g_hSemaphoreBufferFull;
//生產者線程函數
unsigned int __stdcall ProducerThreadFun(PVOID pM)
{
for (int i = 1; i <= END_PRODUCE_NUMBER; i++)
{
//等待有空的緩衝區出現
WaitForSingleObject(g_hSemaphoreBufferEmpty, INFINITE);
oCLockFreeRingQueue.insertData(&i);
ReleaseSemaphore(g_hSemaphoreBufferFull, 1, NULL);
}
printf("生產者完成任務,線程結束運行\n");
return 0;
}
//消費者線程函數
unsigned int __stdcall ConsumerThreadFun_1(PVOID pM)
{
int iGetData = 0;
while (true)
{
//等待非空的緩衝區出現
WaitForSingleObject(g_hSemaphoreBufferFull, INFINITE);
oCLockFreeRingQueue.getData(&iGetData); //實際項目中此處獲得數據的內存建議用深拷貝
//Sleep(50); //some other work to do
ReleaseSemaphore(g_hSemaphoreBufferEmpty, 1, NULL);
}
return 0;
}
unsigned int __stdcall ConsumerThreadFun_2(PVOID pM)
{
int iGetData = 0;
while (true)
{
//等待非空的緩衝區出現
WaitForSingleObject(g_hSemaphoreBufferFull, INFINITE);
oCLockFreeRingQueue.getData(&iGetData);
//Sleep(50); //some other work to do
ReleaseSemaphore(g_hSemaphoreBufferEmpty, 1, NULL);
}
return 0;
}
int main()
{
printf(" 生產者消費者問題 1生產者 2消費者 4緩衝區\n");
printf(" -- by MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n");
//初始化信號量,一個記錄有產品的緩衝區個數,另一個記錄空緩衝區個數.
g_hSemaphoreBufferEmpty = CreateSemaphore(NULL, 4, 4, NULL);
g_hSemaphoreBufferFull = CreateSemaphore(NULL, 0, 4, NULL);
const int THREADNUM = 3;
HANDLE hThread[THREADNUM];
//生產者線程
hThread[0] = (HANDLE)_beginthreadex(NULL, 0, ProducerThreadFun, NULL, 0, NULL);
//消費者線程
hThread[1] = (HANDLE)_beginthreadex(NULL, 0, ConsumerThreadFun_1, NULL, 0, NULL);
hThread[2] = (HANDLE)_beginthreadex(NULL, 0, ConsumerThreadFun_2, NULL, 0, NULL);
WaitForMultipleObjects(THREADNUM, hThread, TRUE, INFINITE);
for (int i = 0; i < THREADNUM; i++)
CloseHandle(hThread[i]);
//銷燬信號量和關鍵段
CloseHandle(g_hSemaphoreBufferEmpty);
CloseHandle(g_hSemaphoreBufferFull);
return 0;
}
#include "stdafx.h"
#include "LockFreeRingQueue.h"
#include <process.h>
BOOL SetConsoleColor(WORD wAttributes)
{
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
if (hConsole == INVALID_HANDLE_VALUE)
return FALSE;
return SetConsoleTextAttribute(hConsole, wAttributes);
}
bool CLockFreeRingQueue::insertData(int *pInData)
{
EnterCriticalSection(&m_gs);
size_t iNextIndex = (m_iWriteIndex + 1) % m_iBufferSize;
if (iNextIndex == m_iReadIndex)
{
LeaveCriticalSection(&m_gs);
return false;
}
else
{
m_iData[m_iWriteIndex] = *pInData;
std::cout<<"生產者在緩衝池第"<<m_iWriteIndex<<"個緩衝區中投放數據"<<*pInData<<std::endl;
m_iWriteIndex = iNextIndex;
LeaveCriticalSection(&m_gs);
return true;
}
}
bool CLockFreeRingQueue::getData(int *pOutData)
{
EnterCriticalSection(&m_gs);
if (m_iReadIndex == m_iWriteIndex)
{
LeaveCriticalSection(&m_gs);
return false;
}
else
{
*pOutData = m_iData[m_iReadIndex];
SetConsoleColor(FOREGROUND_GREEN);
std::cout<<"編號爲"<<GetCurrentThreadId()<<"的消費者從緩衝池中第"<<m_iReadIndex<<"個緩衝區中投放數據"<<*pOutData <<std::endl;
SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
m_iReadIndex = (m_iReadIndex + 1) % m_iBufferSize;
LeaveCriticalSection(&m_gs);
return true;
}
}
#ifndef _LOCKFREERINGQUEUE_H_
#define _LOCKFREERINGQUEUE_H_
#include <Windows.h>
#include <iostream>
class CLockFreeRingQueue
{
public:
CLockFreeRingQueue(const size_t &size) : m_iBufferSize(size + 1), m_iReadIndex(0), m_iWriteIndex(0)
{
m_iData = new int[size];
InitializeCriticalSection(&m_gs);
}
~CLockFreeRingQueue()
{
}
bool insertData(int *pInData);
bool getData(int *pOutData);
private:
size_t m_iReadIndex;
size_t m_iWriteIndex;
size_t m_iBufferSize;
public:
int *m_iData;
CRITICAL_SECTION m_gs;
};
#endif
這個例子比較粗糙,我只是測試了一下,應該可以拿來用。