无锁队列有关问题【1】
来源:互联网 发布:2016全国酒驾车祸数据 编辑:程序博客网 时间:2024/05/21 06:32
无锁队列有关问题【一】
实现无锁队列的关键点有二:
1、各个平台的原子操作或者说CAS原语;
2、ABA问题的理解和解决。
首先来说说这个CAS原语,所谓CAS(Compare And Swap)即比较并交换,在 Intel 处理器中,比较并交换通过指令的 cmpxchg 系列实现。CAS有三个操作数: 内存位置(V)、预期原值(A)和新值(B)。如果内存位置V的值与预期A原值相匹配,那么处理器会自动将该位置值更新为新值B。否则,处理器不做任何操作。无论哪种情况,它都会在 CAS 指令之前返回该位置的值。(在 CAS 的一些特殊情况下将仅返回 CAS 是否成功,而不提取当前值。)CAS 有效地说明了“我认为位置 V 应该包含值 A;如果包含该值,则将 B 放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。”CAS的C语言实现如下:
inline bool CAS2(pointer_t *addr, pointer_t &old_value, pointer_t &new_value)
{
bool ret;
__asm__ __volatile__(
"lock cmpxchg16b %1;\n"
"sete %0;\n"
:"=m"(ret),"+m" (*(volatile pointer_t *) (addr))
:"a" (old_value.ptr), "d" (old_value.tag), "b" (new_value.ptr), "c" (new_value.tag));
return ret;
}
这其中包括了内联汇编代码(这个可以去看看AT&T汇编语法),其中能够支持多线程的并行安全执行的秘诀就在 "lock cmpxchg16b %1;\n"这句中的“lock”,这个lock就和我们基本多线程编程中的锁相当,只不过,这个lock不再是普通的锁,它锁的是地址总线,在多核编程情景下,当已经有CPU的线程A已经访问某地址时,这时地址总线会被锁定,其他CPU核心的线程B无法再访问当前地址,直到A访问完毕之后,其他线程如B才可能访问该地址,这样就保证了线程A访问该地址的原子性操作。
下面是一些有关锁的实现方法:(代码来自Wikipedia的Compare And Swap词条)【内存位置V的值与预期A原值相匹配,那么处理器会自动将该位置值更新为新值B】意思就是说,看一看内存*reg里的值是不是oldval,如果是的话,则对其赋值newval。
1
2
3
4
5
6
7
intcompare_and_swap (int* reg, intoldval,intnewval)
{
intold_reg_val = *reg;
if(old_reg_val == oldval)
*reg = newval;
returnold_reg_val;
}
这个操作可以变种为返回bool值的形式(返回 bool值的好处在于,可以调用者知道有没有更新成功):
1
2
3
4
5
6
7
8
boolcompare_and_swap (int*accum,int*dest,intnewval)
{
if( *accum == *dest ) {
*dest = newval;
returntrue;
}
returnfalse;
}
与CAS相似的还有下面的原子操作:(这些东西大家自己看Wikipedia吧)
· Fetch And Add,一般用来对变量做 +1 的原子操作
· Test-and-set,写值到某个内存位置并传回其旧值。汇编指令BST
· Test and Test-and-set,用来低低Test-and-Set的资源争夺情况
注:在实际的C/C++程序中,CAS的各种实现版本如下:
1)GCC的CAS
GCC4.1+版本中支持CAS的原子操作(完整的原子操作可参看 GCC Atomic Builtins)
1
2
bool__sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)
type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)
2)Windows的CAS
在Windows下,你可以使用下面的Windows API来完成CAS:(完整的Windows原子操作可参看MSDN的InterLocked Functions)
1
2
3
InterlockedCompareExchange ( __inoutLONGvolatile*Target,
__inLONGExchange,
__inLONGComperand);
3) C++11中的CAS
C++11中的STL中的atomic类的函数可以让你跨平台。(完整的C++11的原子操作可参看 Atomic Operation Library)
1
2
3
4
5
6
template<classT >
boolatomic_compare_exchange_weak( std::atomic<T>* obj,
T* expected, T desired );
template<classT >
boolatomic_compare_exchange_weak(volatilestd::atomic<T>* obj,
T* expected, T desired );
再来讲讲这个ABA问题。在进行CAS操作时,因为在更改V值之前,CAS主要是通过访问V的值是否仍然和A相等,所以,在第一次读取V以及对V执行CAS操作之前,如果有其他线程将V的值先从A改为B,而另外的线程又将V的值从B改回了A,这样会使CAS算法混乱。显然,在这种情况下,CAS的操作会成功,这类的问题称为ABA问题。要解决这类问题,就是不再重用A,通常的做法是用标记或版本编号与进行CAS操作的每个值相关联,并原子的更新值和标记
- 无锁队列有关问题【1】
- C++ 无锁队列 ABA <1>
- 环形无锁队列-版本1
- 无锁环形队列
- 无锁队列
- 无锁队列实现
- 无锁队列
- 无锁队列
- 无锁队列
- 无锁队列
- 高效无锁队列
- [c++]无锁队列
- 无锁队列
- Boost无锁队列
- KFIFO无锁队列
- 无锁队列(一)
- MpscLinkedQueue 无锁队列
- 无锁队列入门
- requestWindowFeature(Window.FEATURE_NO_TITLE)
- 关于CSS中的*
- 解密
- 关于数据库的分库分表浅析
- myeclipse10中表单中的JS函数无法写return,onsubmit="return check();"处出错
- 无锁队列有关问题【1】
- 有理数类的定义与实现
- HDOJ刷题(1091)
- HBase笔记:存储结构
- 部署java web到远程服务器
- log4Cpp学习(二)—log4Cpp构成要素
- linux逆向分析之ELF文件详解
- Mybatis migration使用初探
- 物联12:AlOHA算法