【多线程】(十二)多线程十大经典案例之一双线程读写队列数据

参考自 http://blog.csdn.net/morewindows/article/details/8646902

 

如果将队列看成缓冲区,这个案例明显是个生产者消费者问题(见《秒杀多线程第十篇生产者消费者问题》)。因此我们仿照生产者消费者的思路来具体分析下案例中的“等待”情况:

    1.     当队列为空时,读取数据线程必须等待写入数据向队列中写入数据。也就是说当队列为空时,读取数据线程要等待队列中有数据

    2.     当队列满时,写入数据线程必须等待读取数据线程向队列中读取数据。也就是说当队列满时,写入数据线程要等待队列中有空位

访问队列时,需要互斥吗?这将依赖于队列的数据结构实现,如果使用STL中的vector,由于vector会动态增长。因此要做互斥保护。如果使用循环队列,那么读取数据线程拥有读取指针,写入数据线程拥有写入指针,各自将访问队列中不同位置上的数据,因此不用进行互斥保护。

分析完毕后,再来考虑使用什么样的数据结构,同样依照《秒杀多线程第十篇生产者消费者问题》中的做法。使用两个信号量,一个来记录循环队列中空位的个数,一个来记录循环队列中产品的个数(非空位个数)。代码非常容易写出,下面给出完整的源代码。

//1 生产者 2消费者 4缓冲区


#include "stdafx.h"
#include "process.h"
#include "windows.h"
#include "time.h"

const int QUEUE_LEN = 5;
int g_arrDataQueue[QUEUE_LEN];
int g_i, g_j, g_nDataNum;


CRITICAL_SECTION g_cs;
HANDLE g_hSemaphoreBufferEmpty ,g_hSemaphoreBufferFull;

//设置控制台输出颜色
BOOL SetConsoleColor(WORD wAttributes)
{
	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	if (hConsole == INVALID_HANDLE_VALUE)
		return FALSE;
	return SetConsoleTextAttribute(hConsole,wAttributes);
}



//读取线程函数
unsigned int __stdcall ReaderThreadFun(PVOID pM)
{
	int nData = 0;
	while (nData < 20)
	{
		//等待有空的缓冲区出现
		WaitForSingleObject(g_hSemaphoreBufferFull,INFINITE);
		nData = g_arrDataQueue[g_i];
		g_i = (g_i + 1) % QUEUE_LEN ;

		//互斥的访问缓冲区
		EnterCriticalSection(&g_cs);
		printf("从队列中读取数据%d\n",nData);
		LeaveCriticalSection(&g_cs);
		Sleep(rand()%300);
		ReleaseSemaphore(g_hSemaphoreBufferEmpty ,1 ,NULL);
	}
	return 0;
}

//写数据线程
unsigned int __stdcall WriterThreadFun(PVOID pM)
{
	int nData = 0;
	while (nData < 20)
	{
		//等待非空的缓冲区出现
		WaitForSingleObject(g_hSemaphoreBufferEmpty,INFINITE);
		g_arrDataQueue[g_j] = ++nData;  
		g_j = (g_j + 1) % QUEUE_LEN;  


		EnterCriticalSection(&g_cs);
		SetConsoleColor(FOREGROUND_GREEN);
		printf("    将数据%d写入队列\n", nData); 
		SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);

		LeaveCriticalSection(&g_cs);
		//通知缓冲区已经为空
		Sleep(rand() % 300); 
		ReleaseSemaphore(g_hSemaphoreBufferFull ,1 ,NULL);
	}
	return 0;
}

int main()
{
	 printf(" ---------- 双线程读写队列数据\n");  

	InitializeCriticalSection(&g_cs);
	g_hSemaphoreBufferEmpty = CreateSemaphore(NULL ,QUEUE_LEN,QUEUE_LEN,NULL);
	g_hSemaphoreBufferFull = CreateSemaphore(NULL ,0,QUEUE_LEN,NULL);
	
	srand(time(NULL));
	g_i = 0;
	g_j = 0;

	HANDLE hThread[2] ;

	hThread[0] = (HANDLE)_beginthreadex(NULL ,0 ,ReaderThreadFun,NULL ,0 ,NULL );
	hThread[1] = (HANDLE)_beginthreadex(NULL ,0 ,WriterThreadFun ,NULL ,0 ,NULL );

	WaitForMultipleObjects(2 ,hThread ,TRUE ,INFINITE);
	for (int i = 0;i<2 ;i++)
	{
		CloseHandle(hThread[i]);
	}

	//销毁事件和关键段
	CloseHandle(g_hSemaphoreBufferEmpty);
	CloseHandle(g_hSemaphoreBufferFull);
	DeleteCriticalSection(&g_cs);
	return 0;
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值