gitclone 一个tag的地址_一个无锁队列和FreeList实现

代码实现了这篇文章中的无锁队列。

fangcun:简单,高效,实用的非阻塞(无锁)和阻塞并行队列算法​zhuanlan.zhihu.com

无锁队列需要实现一个FreeList来避免一个线程释放了结点,而另一个线程仍在访问该结点的问题,如图所示的语句就存在这个问题:

880d7d9fee65bfd942f4721540f43e80.png

代码使用mingw64在windows下成功编译,使用gcc内建的原子操作函数。

且实现代码入队和出队操作的每条语句依赖前一语句,编译器不会进行语句级的重排。

FreeList使用了一个技巧来使FreeList的结点和无锁队列的结点使用完全相同的内存,这样结点不是在FreeList中,就是在无锁队列中,不会出现泄漏问题。

FreeList的Alloc(给无锁队列分配结点)和Free操作(这个Free操作是给无锁队列用来将结点放入FreeList中)也是无锁的。

FreeList自身的释放结点操作需要在安全的地方(非竞争环境)进行。

FreeList的最大结点数等于无锁队列中元素最多时的元素个数。

无锁队列中的元素个数没有限制,这里的FreeList的最大结点数不是指FreeList存在大小限制,而是指无锁队列中Free的元素会被放进FreeList重复使用,所以FreeList的最大结点数不可能超过无锁队列的峰值元素数。

无锁队列中的结点可以安全地放入FreeList中重复使用,即使存在多个线程持有结点尝试出队结点,也只有一个可以成功出队,也就是结点只被放入FreeList一次,不会被其它线程再次放入,放入FreeList的结点,可能仍然被其它线程持有,但它接下来的CAS会失败,但我们不能直接释放结点内存,可以对结点进行写操作,其它线程虽然持有结点,但只进行读操作,如果我们直接释放结点内存,其它线程的读操作就会crash整个程序(读的内存地址非法),这也是使用FreeList的原因,其它线程持有结点,也不影响FreeList分配它给无锁队列重新使用。

使用__ATOMIC_RELAXED内存顺序的原因是查阅Intel64文档,文档表明load,store可以在一定程度上保证线程间的内存可见性。

__ATOMIC_RELAXED内存顺序的_atomic_load只是一个原子操作,不会作为编译器优化屏障。

文档地址:

http://120.52.51.18/www.cs.cmu.edu/~410-f10/doc/Intel_Reordering_318147.pdf​120.52.51.18

下面是我实现的无锁队列代码,欢迎大家讨论。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值