windows多線程多緩衝區單生產者多消費者

前幾天讀了一篇文章,介紹線程同步的。講到但生產者多消費者的時候,運用了一個例子文章的博客地址:

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
這個例子比較粗糙,我只是測試了一下,應該可以拿來用。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章