计算机cas lock键的作用,无锁编程lock-free和CAS

lock-free

什么是lock-free,简单的说就是不直接使用mutex,减少锁在系统中占用的开销。相比于基于锁的算法而言,Lock-free 算法具有明显的特征:某个线程在执行数据访问时挂起不会阻碍其他的线程继续执行。这意味着在任意时刻,多个 lock-free 线程可以同时访问同一数据而不产生数据竞争或者损坏。

上面的定义保证了 lock-free 程序中的一组线程中至少有一个可以顺利的执行而不产生阻塞,从而确保整个程序的顺利执行。lock-free中常见的就是使用cas来代替加锁。

CAS

什么是CAS?CAS的本质是把compare-and-swap封装为一个原子操作。伪代码如下:

// 伪代码,整个过程是 atomic,不可被中断

bool compare_and_swap(int * p, int old_val, int new_val)

{

if (*p == old_val)

{

*p = new_val;

return true;

}

return false;

}

gcc提供的类似的接口:

// for gcc

bool __sync_bool_compare_and_swap(type *ptr, type oldval, type newval, ...)

type __sync_val_compare_and_swap(type *ptr, type oldval, type newval, ...)

// for C++11

template

bool atomic_compare_exchange(T* pointer, T* expected, T desired);

// TODO

compare_exchange_weak

使用CAS的接口可以很方便的实现一个无锁的容器。比如stack

void Stack::push(int val, int debug_thread_info)

{

while (true) {

Node * new_obj = new Node(val);

if (new_obj == NULL) {return;}

new_obj->extra_info = debug_thread_info;

Node *next_ptr = this->_top;

new_obj->next = next_ptr;

// 将栈顶指针指向新节点,CAS 直到成功

if (this->_top.compare_exchange_weak(next_ptr, new_obj)) {

return;

}

}

}

Node* Stack::pop()

{

while (true) {

Node *cur_ptr = this->_top;

if (!cur_ptr) {

return NULL;

}

Node *next_ptr = cur_ptr->next;

// 将栈顶指针指向下一节点,CAS 直到成功

if (this->_top.compare_exchange_weak(cur_ptr, next_ptr)) {

return cur_ptr;

}

}

}

ABA问题

一个线程在cas的判断中被切换出去,另外一个线程把a改成了b,又改回了a。等到原线程切换回来,比较当前值和a,发现一致,于是把当前值cas交换,设置为新值。举个栗子:

thread1:

top

a -> b -> c

^ ^

cur_ptr next_ptr

1. thread1 即将执行cas

2. thread2 切入,thread1挂起

3. thread2 连续pop 两个元素

4. thread2 push元素,恰好是a

于是:

thread2:

a -> c

5. thread1切回来继续执行

thread1判断 top == cur_ptr,于是吧top设置为b。

但是b已经不存在这个链表了,于是stack的top指针被设置错误。

如何避免ABA问题

ABA问题的本质是内存回收。用刚才的例子来说,需要保证a被弹出之后,内存不会立刻被回收,下次分配内存的时候,不会在恰好把这段内存分配出去。以至于CAS判断的时候,通过地址判断发现是一致的,但是实际上是有可能被修改过的。

常见的一些解决办法:

使用版本号

使用定长数组(提前分配好内存),不涉及内存分配,避免aba出现。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值