自定义信号量

在程序中,参考了SAFMQ中对事件进行封装用的信号量,但是有个地方触发了事件,但是另外一个地方没有激活,导致程序挂掉。所以自己另写了一个自定义的信号量,并编写程序进行测试。是OK的啊

先谈谈应用场景,信号量用很多,比如计数信号量,互斥信号量等等,我在此处主要还是用来在线程间同步用的。

一个线程获取数据(RecvMsgThread),一个线程存放数据(SendMsgThread)。但是数据中心中并不一定有数据,所以此处该线程就会阻塞,直至存放数据线程将数据放到数据中心中,并释放信号量,这样获取线程被激活,可以继续获取数据,其实就这么一个简单的应用场景。

 

看看信号量是如何封装的:

#ifndef	 _CSIGNAL_H 
#define  _CSIGNAL_H

class  _declspec(dllexport) CSignal
{
public:
	enum Result { SIGNAL_TIMEOUT, SIGNAL_SET, SIGNAL_ERROR };

	CSignal();
	~CSignal();

	CSignal::Result  WaitForSignal(long waitMilSecs);
	void ReleaseSignal();

	
private:
	HANDLE	 m_customSignal;
};

#endif

#include "stdafx.h"
#include "CustomSignal.h"

CSignal::CSignal()
{
	m_customSignal = CreateSemaphore(   
					NULL,		// 默认安全属性  
					0,		// 初始化计数器 
					1,		// 最大计数
					NULL);	        // 未命名  
};


CSignal::~CSignal()
{
	CloseHandle(m_customSignal);
};

CSignal::Result CSignal::WaitForSignal(long waitMilSecs)
{
	DWORD result;

	if (waitMilSecs < 0)
		result = ::WaitForSingleObject(m_customSignal,  INFINITE);//表示一直等待
	else
		result = ::WaitForSingleObject(m_customSignal,	waitMilSecs);


	if (result == WAIT_OBJECT_0)			//事件收到通知
		return CSignal::SIGNAL_SET;
	else if (result == WAIT_TIMEOUT)		//事件未收到通知,超时
		return CSignal::SIGNAL_TIMEOUT;

	return CSignal::SIGNAL_ERROR;
};

void CSignal::ReleaseSignal()
{
		ReleaseSemaphore(m_customSignal,// 信号量句柄  
				1,		// 释放后计数器减1   
				NULL );		// 获得计数  
}

在看看我是如何测试的。

首先要有两个线程都访问的数据中心,定义如下:

#ifndef _DATA_SOURCE_H
#define  _DATA_SOURCE_H

#include <vector>
#include "../COMMUtil/Mutex.h"
#include "../COMMUtil/Signal.h"
#include "../COMMUtil/CustomSignal.h"
#include <iostream>
using namespace  std;
class DataSource
{
public:
	int m_nDataLen;
	vector<int>  dataSource;

	Mutex  m_mutex;    //对资源进行互斥
	CSignal   m_signal;    //没有资源阻塞,有资源提醒

        //产生数据
	void ProduceData(int nInputData)
	{
		MutexLock mutexLock(&m_mutex);

		dataSource.push_back(nInputData);
		m_signal.ReleaseSignal();
		cout<<"DataSource: ProduceData: ReleaseSignal"<<endl;
	};

	void ConsumeData(int& nOutputData)
	{
		MutexLock mutexLock(&m_mutex);
		if (dataSource.empty())
		{
			CSignal::Result ret = m_signal.WaitForSignal(5*1000);

			if (ret == CSignal::SIGNAL_SET)
			    cout<<"DataSource: ConsumerData: Signal Released"<<endl;
		}
		if (dataSource.size() > 0)
		{
			vector<int>::iterator iter = dataSource.begin();
			nOutputData = *iter;
			dataSource.erase(iter);
			cout<<"Consumer:  "<<nOutputData<<endl;
		}
	};
};
#endif

 

 发送数据线程定义如下:

#pragma once
#include "../COMMUtil/Thread.h"
#include <vector>
#include "DataSource.h"

using namespace std;

class SendMsgThread :public Thread
{

	private:
		DataSource* m_pDataSource;
	
	public:
		SendMsgThread(void);
		SendMsgThread(DataSource* pDataSource);
		~SendMsgThread(void);

	protected:
	        void *run();
			
};
SendMsgThread::SendMsgThread(DataSource* pDataSource)
{
	m_pDataSource = pDataSource;
}


void * SendMsgThread::run()
{
	cout<<"SendMsgThread...................."<<endl;

	for (int i  = 0; i < 1000000; i++)
	{
		Sleep(2*100);
		m_pDataSource->ProduceData(i);
	}
			
	return NULL;
}

接收数据线程定义:

 

//接收数据线程

#pragma once

#include "../COMMUtil/Thread.h"
#include "DataSource.h"


class ReceiveMsgThread :public Thread
{
	private:
		DataSource* m_pDataSource;
					
			
	public:
		ReceiveMsgThread(void);
		ReceiveMsgThread(DataSource* pDataSource);
		~ReceiveMsgThread(void);

	protected:
		void* run();

};

 

ReceiveMsgThread::ReceiveMsgThread(DataSource* pDataSource)
: m_pDataSource(pDataSource){

}


void* ReceiveMsgThread::run()
{
	cout<<"ReceiveMsgThread...................."<<endl;
	int	data;

	while(1)
	{
		m_pDataSource->ConsumeData(data);
			
	}
	return NULL;
		
}

 

在main函数中做如下定义:

int _tmain(int argc, _TCHAR* argv[])
{
       DataSource* pDataSource = new DataSource();
       ReceiveMsgThread* pRecvThread = new ReceiveMsgThread(pDataSource);
       SendMsgThread* pSendThread = new SendMsgThread(pDataSource);

	pRecvThread->start();

	::Sleep(5 * 1000);

	pSendThread->start();
	

	getchar();

	return 0;
}

运行结果如下:

每次信号量的获取前面必有一次信号量的释放!

转载于:https://my.oschina.net/myspaceNUAA/blog/54558

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值