实现一个lockfree 的队列

看梁总的题目,实现高速队列,百思不得其解。

后来看了答案,算是比葫芦画瓢实现了一个。

其实最重要的两点:

1。实现一个原子加加,用来得到一个唯一下标。

2.用一个永远不会使用的值当标记,验证该下标对应的位置是否有值。

代码如下:

 

// 临界锁,线程安全
// 必须要有一个不会用的空值,
template <class T_Key>
class CQQueue_Lockfree
{
public:
	CQQueue_Lockfree()
	{
		m_lMaxQueueSize = -1;
		m_tpQueue = NULL;

		m_lBegPos = 0;
		m_lEndPos = 0;
	};

	~CQQueue_Lockfree()
	{
		if(m_tpQueue)
			delete m_tpQueue;
	};

	var_4 InitQueue(var_4 lMaxQueueSize, T_Key null)
	{
		m_lMaxQueueSize = lMaxQueueSize;
		m_tpQueue = new T_Key[m_lMaxQueueSize];
		if(m_tpQueue == NULL)
			return -1;
		m_lBegPos = 0;
		m_lEndPos = 0;
		m_null = null;

		for( var_4 i = 0; i < lMaxQueueSize; i++ )
		{
			m_tpQueue[i] = null;
		}
		
		return 0;
	};

	void ResetQueue()
	{
		m_lBegPos = 0;
		m_lEndPos = 0;	
	};

	void ClearQueue()
	{
		if(m_tpQueue)
		{
			delete m_tpQueue;
			m_tpQueue = NULL;
		}

		m_lMaxQueueSize = -1;
		m_lBegPos = 0;
		m_lEndPos = 0;
	};

	void PushData(T_Key tKey)
	{
		register var_u8 cnt =1;
		var_u8 pos = fetch_and_add(&m_lEndPos, cnt)%m_lMaxQueueSize;

		while( m_null != m_tpQueue[pos] )
			cp_sleep(1);

		m_tpQueue[pos] = tKey;
	};

	T_Key PopData()
	{
		register var_u8 cnt =1;
		var_u8 pos = fetch_and_add(&m_lBegPos, cnt)%m_lMaxQueueSize;

		T_Key*p = m_tpQueue+pos;
		while( m_null == *p )
			cp_sleep(1);

		T_Key ret = *p;
		*p = m_null;
		
		return ret;
	};
private:
	var_4 m_lMaxQueueSize;
	T_Key* m_tpQueue;
	T_Key m_null;

	var_u4 m_lBegPos;
	var_u4 m_lEndPos;
};

 

上面是我的代码,梁总的实现更高效,

首先,他认为队列足够长,并且取得足够快,所以在push时,根本不检查队头压队尾的情况。

在pop时,只检查队头-队尾的长度,小于一个阈值就不再取,由于只用于高速队列,会一直有数据被push,所以不会发生阈值以内的数据被延时。

 

经过测试,这种方式比用锁少了40%。

10亿次放入和读取,10线程花费200秒。

不过梁总测试说8核1.5GHz花了88秒,但在我24核

vendor_id       : GenuineIntel
cpu family      : 6
model           : 45
model name      : Intel(R) Xeon(R) CPU E5-2630 0 @ 2.30GHz
stepping        : 7
cpu MHz         : 2300.469
cache size      : 15360 KB

的机器上,也只跑了200秒,真是奇怪。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值