C++ 无锁队列实现
上源码
#ifndef __GLOBAL_LOCK_FREE_QUEUE_H__
#define __GLOBAL_LOCK_FREE_QUEUE_H__ #include <atomic>
#include <list> #ifdef _WINDOWS
#include <windows.h>
//PVOID __cdecl InterlockedCompareExchangePointer(
// _Inout_ PVOID volatile *Destination,
// _In_ PVOID Exchange,
// _In_ PVOID Comparand
// );
//
//Parameters
// Destination [in, out]
//A pointer to a pointer to the destination value.
// Exchange [in]
//The exchange value.
// Comparand [in]
//The value to compare to Destination.
// Return value
// The function returns the initial value of the Destination parameter.
// Remarks
// The function compares the Destination value with the Comparand value. If the Destination value is equal to the Comparand value, the Exchange value is stored in the address specified by Destination. Otherwise, no operation is performed.
// On a 64-bit system, the parameters are 64 bits and must be aligned on 64-bit boundaries; otherwise, the function will behave unpredictably. On a 32-bit system, the parameters are 32 bits and must be aligned on 32-bit boundaries.
// The interlocked functions provide a simple mechanism for synchronizing access to a variable that is shared by multiple threads. This function is atomic with respect to calls to other interlocked functions.
#define __sync_bool_compare_and_swap(a,b,c) (InterlockedCompareExchangePointer((void*volatile*)a,c,b), (*a)==(c))
#endif namespace DataCache
{ template <typename T>
class LinkList
{
public:
T data;
LinkList<T> *next;
};// class LinkeList<T> template <typename T>
class LockFreeQueue
{
public:
LockFreeQueue(); void push_back(T t); T pop_front(void); bool isEmpty(void); int GetLength(); private:
LinkList<T> *head_;
LinkList<T> *tail_;
std::_Atomic_integral_t elementNumbers_;
}; // class LockFreeQueue template <typename T>
LockFreeQueue<T>::LockFreeQueue()
:head_(NULL),
tail_(new LinkList<T>),
elementNumbers_()
{
head_ = tail_;
tail_->next = NULL;
} template <typename T>
void LockFreeQueue<T>::push_back(T t)
{
auto newVal = new LinkList<T>;
newVal->data = t;
newVal->next = NULL; LinkList<T> *p;
do
{
p = tail_;
} while (!__sync_bool_compare_and_swap(&tail_->next, NULL, newVal)); //move tail_
__sync_bool_compare_and_swap(&tail_, tail_, newVal);
elementNumbers_++;
} template <typename T>
T LockFreeQueue<T>::pop_front()
{
LinkList<T> *p; do
{
//record the first node.
p = head_->next;
if (!p)
{
return ;
}
} while (!__sync_bool_compare_and_swap(&head_->next, p, p->next)); if (elementNumbers_ > ) elementNumbers_--;
if (elementNumbers_ == )
{
// if the queue is empty then the tail to header.
do
{ } while (!__sync_bool_compare_and_swap(&tail_, p, head_));
} return p->data;
} template <typename T>
bool LockFreeQueue<T>::isEmpty()
{
if (elementNumbers_ == )
{
return true;
}
else
{
return false;
}
} template <typename T>
int LockFreeQueue<T>::GetLength()
{
return elementNumbers_;
} }// namespace DataCache #endif
源码解析:
重点在函数InterlockedCompareExchangePointer(a,c,b),其作用为如果a==b,则修改a的值为c,这是微软提供的一个原子操作的API,这里面通过定义这个宏,来进行queue入队列和出队列时的指针修改,达到无锁操作的目的,可以大幅提高队列的操作性能,避免过程中进行加锁操作。在GCC中已经原生支持了__sync_bool_compare_and_swap,所以这个宏的作用是针对MSVC版本提供的类似函数。
测试代码:
#include"lockFreeQueue.h" DataCache::LockFreeQueue<int> queue; void func1(void)
{
for(int i = ; i < ; i++)
{
queue.push_back(i);
}
} void func2(void)
{
for(int i = ; i < ; i++)
{
queue.push_back(i);
}
} void func5(void)
{
for(int i = ; i < ; i++)
{
queue.push_back(i);
}
} void func4(void)
{
for(int i = ; i < ; i++)
{
queue.push_back(i);
}
} void func3(void)
{
while (!queue.isEmpty())
{
std::cout<<queue.pop_front()<<" ";
} std::cout<<std::endl;
} int main(int argc,char **argv)
{
std::thread t1(func1);
std::thread t2(func2);
std::thread t5(func5);
std::thread t6(func4); t1.join();
t2.join();
t5.join();
t6.join(); int length=queue.GetLength();
assert(length==500000);
return ;
}
C++ 无锁队列实现的更多相关文章
- 无锁队列以及ABA问题
队列是我们非常常用的数据结构,用来提供数据的写入和读取功能,而且通常在不同线程之间作为数据通信的桥梁.不过在将无锁队列的算法之前,需要先了解一下CAS(compare and swap)的原理.由于多 ...
- HashMap的原理与实 无锁队列的实现Java HashMap的死循环 red black tree
http://www.cnblogs.com/fornever/archive/2011/12/02/2270692.html https://zh.wikipedia.org/wiki/%E7%BA ...
- zeromq源码分析笔记之无锁队列ypipe_t(3)
在上一篇中说到了mailbox_t的底层实际上使用了管道ypipe_t来存储命令.而ypipe_t实质上是一个无锁队列,其底层使用了yqueue_t队列,ypipe_t是对yueue_t的再包装,所以 ...
- boost 无锁队列
一哥们翻译的boost的无锁队列的官方文档 原文地址:http://blog.csdn.net/great3779/article/details/8765103 Boost_1_53_0终于迎来了久 ...
- 一个可无限伸缩且无ABA问题的无锁队列
关于无锁队列,详细的介绍请参考陈硕先生的<无锁队列的实现>一文.然进一步,如何实现一个不限node数目即能够无限伸缩的无锁队列,即是本文的要旨. 无锁队列有两种实现形式,分别是数组与链表. ...
- 无锁队列--基于linuxkfifo实现
一直想写一个无锁队列,为了提高项目的背景效率. 有机会看到linux核心kfifo.h 原则. 所以这个实现自己仿照,眼下linux我们应该能够提供外部接口. #ifndef _NO_LOCK_QUE ...
- CAS简介和无锁队列的实现
Q:CAS的实现 A:gcc提供了两个函数 bool __sync_bool_compare_and_swap (type *ptr, type oldval, type newval, ...)// ...
- Go语言无锁队列组件的实现 (chan/interface/select)
1. 背景 go代码中要实现异步很简单,go funcName(). 但是进程需要控制协程数量在合理范围内,对应大批量任务可以使用"协程池 + 无锁队列"实现. 2. golang ...
- 基于无锁队列和c++11的高性能线程池
基于无锁队列和c++11的高性能线程池线程使用c++11库和线程池之间的消息通讯使用一个简单的无锁消息队列适用于linux平台,gcc 4.6以上 标签: <无> 代码片段(6)[ ...
- folly无锁队列正确性说明
folly无锁队列是facebook开源的一个无所队列,使用的是单向链表,通过compare_exchange语句实现的多生产多消费的队列,我曾经花了比较多的时间学习memory_order的说明,对 ...
随机推荐
- [Python] 网络编程之TCP编程
转自:TCP编程 - 廖雪峰的官方网站 Socket是网络编程的一个抽象概念.通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协 ...
- LMS算法
一.感知器算法和LMS算法 感知器和自适应线性元件在历史上几乎是同时提出的,并且两者在对权值的调整的算法非常相似.它们都是基于纠错学习规则的学习算法. 感知器算法存在如下问题:不能推广到一般的前向网络 ...
- jqprint 打印分页
再要分页的结尾处加上<div style="page-break-after:always;"></div> 就可以了
- UVA 10815:Andy's First Dictionary(STL)
题意:给出一段英文,里面包含一些单词,空格和标点,单词不区分大小写,默认都为小写.按照字典序输出这些单词(这些单词不能有重复,字母全部变成小写) stringstream:包含在头文件#include ...
- CTF-练习平台-Misc之 妹子的陌陌
二十五.妹子的陌陌 该图片后缀名为rar,发现里面有一个文本 但是解压需要密码,应为不知道是几位的没法爆破,观察图片后发现红色字体:“喜欢我吗.”尝试一下,居然是密码,将文本解压出来 内容如下: 嘟嘟 ...
- test20180919 选择客栈
题意 分析 不难发现把增加人数看成减少人数,上限是w 看成总数是w,问题就变成了询问有多少个子区间没有0. 考虑这个问题困难在哪里,就是区间加减法让我们不好判断0 的位置. 因为题目保证每个位置的值非 ...
- socket套接字和驱动绑定分析
1. socket()系统调用 socket系统调用是哪个:socket()有3个参数,因此搜索SYSCALL_DEFINE3,然后在检索socket即可. SYSCALL_DEFINE3(socke ...
- leetcode:Reverse Words in a String【Python版】
class Solution: # @param s, a string # @return a string def reverseWords(self, s): ss = s.split(&quo ...
- Promise 知识点
.done() Promise 对象的回调链,不管以then方法或catch方法结尾,要是最后一个方法抛出错误,都有可能无法捕捉到(因为 Promise 内部的错误不会冒泡到全局).因此,我们可以提供 ...
- jmeter测试TCP服务器/模拟发送TCP请求
jmeter测试TCP服务器,使用TCP采样器模拟发送TCP请求. TCP采样器:打开一个到指定服务器的TCP / IP连接,然后发送指定文本并等待响应. jmeter模拟发送TCP请求的方法: 1. ...