CAS

一般采用原子级的read-modify-write原语来实现Lock-Free算法,其中LL和SC是Lock-Free理论研究领域的理想原语,但实现这些原语需要CPU指令的支持,非常遗憾的是目前没有任何CPU直接实现了SC原语。根据此理论,业界在原子操作的基础上提出了著名的CAS(Compare-And-Swap)操作来实现Lock-Free算法,Intel实现了一条类似该操作的指令:cmpxchg8。

CAS原语负责将某处内存地址的值(1个字节)与一个期望值进行比较,如果相等,则将该内存地址处的值替换为新值,CAS 操作伪码描述如下:

Bool CAS(T* addr, T expected, T newValue)

{

if(*addr == expected )

{

*addr=  newValue;

returntrue;

}

else

returnfalse;

}

CAS实际操作

do

{

备份旧数据;

基于旧数据构造新数据;

}while(!CAS(内存地址,备份的旧数据,新数据))

就是指当两者进行比较时,如果相等,则证明共享数据没有被修改,替换成新值,然后继续往下运行;如果不相等,说明共享数据已经被修改,放弃已经所做的操作,然后重新执行刚才的操作。容易看出CAS操作是基于共享数据不会被修改的假设,采用了类似于数据库的commit-retry的模式。当同步冲突出现的机会很少时,这种假设能带来较大的性能提升。

CAS的Linux解法

cmpxchg先比较内存地址的值是否与传入的值相等,如果相等则执行xchg逻辑。

inline int CAS(unsigned long* mem, unsignedlong newval, unsigned long oldval)

{

__typeof(*mem) ret;

//这里测试的使用64位系统,如果是32位,这里使用cmpschgl

__asm__volatile ("lock; cmpxchgq %2,%1"

:"=a"(ret), "=m"(*mem)

:"r"(newval), "m"(*mem), "0"(oldval));

returnret==oldval;

}

CAS举例(简单应用AtomicInc)

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <stdint.h> int count = 0; inline int CAS(unsigned long* mem, unsigned long oldval, unsigned long newval)
{
__typeof (*mem) ret;
// 这里测试的使用64位系统,如果是32位,这里使用cmpschgl
__asm __volatile ("lock; cmpxchgq %2,%1"
: "=a"(ret), "=m"(*mem)
: "r"(newval), "m"(*mem), "0"(oldval));
return ret==oldval;
} void AtomicInc(int* addr)
{
int oldval;
int newval;
do
{
oldval = *addr;
newval = oldval+1;
} while(!CAS((unsigned long*)addr, oldval, newval));
} void *test_func(void *arg)
{
int i=0;
int confict = 0;
for(i=0;i<2000000;++i)
{
AtomicInc(&count);
}
return NULL;
} int main(int argc, const char *argv[])
{
pthread_t id[20];
int i = 0; uint64_t usetime;
struct timeval start;
struct timeval end; gettimeofday(&start,NULL); for(i=0;i<20;++i)
{
pthread_create(&id[i],NULL,test_func,NULL);
} for(i=0;i<20;++i)
{
pthread_join(id[i],NULL);
} gettimeofday(&end,NULL); usetime = (end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec);
printf("count = %d, usetime = %lu usecs\n", count, usetime);
return 0;
}

CAS举例(复杂应用)

struct Node
{
Node* next;
int data;
}
Node* head = NULL; void push(int t)
{
Node* node = new Node(t);
do
{
node->next = head;
} while (!CAS(&head, node->next, node));
} bool pop(int&t )
{
Node* current = head;
while(current)
{
if (CAS(&head, current, current->next)) // ABA问题
{
t = current->data;
return true;
}
current = head;
}
return false;
}

ABA问题

一般的CAS在决定是否要修改某个变量时,会判断一下当前值跟旧值是否相等。如果相等,则认为变量未被其他线程修改,可以改。 
但是,“相等”并不真的意味着“未被修改”。另一个线程可能会把变量的值从A改成B,又从B改回成A。这就是ABA问题。
很多情况下,ABA问题不会影响你的业务逻辑因此可以忽略。但有时不能忽略,这时要解决这个问题,一般的做法是给变量关联一个只能递增、不能递减的版本号。在compare时不但compare变量值,还要再compare一下版本号。 
Java里的AtomicStampedReference类就是干这个的。

版权声明:本文为博主原创文章,未经博主允许不得转载。

无锁编程(四) - CAS与ABA问题的更多相关文章

  1. 4.锁--无锁编程以及CAS

    无锁编程以及CAS 无锁编程 / lock-free / 非堵塞同步 无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被堵塞的情况下实现变量的同步,所以也叫非堵塞同步(Non-b ...

  2. 无锁编程以及CAS

    无锁编程 / lock-free / 非阻塞同步 无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(Non-blocking Sy ...

  3. 【多线程】无锁编程以及CAS

    无锁编程 / lock-free / 非阻塞同步 无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(Non-blocking Sy ...

  4. 【Java并发编程】2、无锁编程:lock-free原理;CAS;ABA问题

    转自:http://blog.csdn.net/kangroger/article/details/47867269 定义 无锁编程是指在不使用锁的情况下,在多线程环境下实现多变量的同步.即在没有线程 ...

  5. C++11原子操作与无锁编程(转)

    不讲语言特性,只从工程角度出发,个人觉得C++标准委员会在C++11中对多线程库的引入是有史以来做得最人道的一件事:今天我将就C++11多线程中的atomic原子操作展开讨论:比较互斥锁,自旋锁(sp ...

  6. C++性能榨汁机之无锁编程

    C++性能榨汁机之无锁编程 来源 http://irootlee.com/juicer_lock_free/ 前言 私以为个人的技术水平应该是一个螺旋式上升的过程:先从书本去了解一个大概,然后在实践中 ...

  7. [转]透过 Linux 内核看无锁编程

    非阻塞型同步 (Non-blocking Synchronization) 简介 如何正确有效的保护共享数据是编写并行程序必须面临的一个难题,通常的手段就是同步.同步可分为阻塞型同步(Blocking ...

  8. 海量并发的无锁编程 (lock free programming)

    最近在做在线架构的实现,在线架构和离线架构近线架构最大的区别是服务质量(SLA,Service Level Agreement,SLA 99.99代表10K的请求最多一次失败或者超时)和延时.而离线架 ...

  9. Java CAS同步机制 原理详解(为什么并发环境下的COUNT自增操作不安全): Atomic原子类底层用的不是传统意义的锁机制,而是无锁化的CAS机制,通过CAS机制保证多线程修改一个数值的安全性。

    精彩理解:  https://www.jianshu.com/p/21be831e851e ;  https://blog.csdn.net/heyutao007/article/details/19 ...

随机推荐

  1. CoreData (表结构变化处理)

    引言: Core Data 是 iOS 3.0 以后引入的数据持久化解决方案,其原理是对SQLite的封装,是开发者不需要接触SQL语句,就可以对数据库进行的操作. 其编码方式和原理结构方面较为特殊, ...

  2. 腾讯开源的轻量级CSS3动画库:JX.Animate

          JX.Animate 是由腾讯前端团队 AlloyTeam 推出的一个 CSS3 动画库,通过 JX(腾讯的前端框架)插件的形式提供. Why CSS3 众所周知在支持HTML5的浏览器中 ...

  3. CSS自定义文件上传按钮

    今天一同事问我文件上传按钮的问题,情况是这样的,他页面上有3个按钮,分为左中右三个,左边的位按钮甲,右边的位按钮乙,而中间的就是个文件选择按钮,情况大概是这个样子的: 两边的按钮都有了样式,但中间的选 ...

  4. Sublime Text 编辑器

    1.从http://www.sublimetext.com/2 下载Sublime Text 2编辑器. 2.安装Package Control 管理器,用于管理和安装插件包. 下载地址:https: ...

  5. Comet技术浅论

    1.如何实现一个轮询? function getMessage(url,callback){ var XHR=new XMLHttpRequest(); XHR.open('get',url,true ...

  6. [C++]内存字节对齐

    当我们写一个class类,然后sizeof(),然后发现这个值往往比你想象的大,这是为什么呢?这里就要讲到内存对齐的问题. 先来看一下内存对齐的几条原则: 1.对于class(struct/union ...

  7. ***ECharts图表入门和最佳实践

    ECharts数据图表系统? 5分钟上手! [ECharts简介] ECharts开源来自百度商业前端数据可视化团队,基于html5 Canvas,是一个纯Javascript图表库,提供直观,生动, ...

  8. 2014多校第一场 E 题 || HDU 4865 Peter's Hobby (DP)

    题目链接 题意 : 给你两个表格,第一个表格是三种天气下出现四种湿度的可能性.第二个表格是,昨天出现的三种天气下,今天出现三种天气的可能性.然后给你这几天的湿度,告诉你第一天出现三种天气的可能性,让你 ...

  9. 传说中的WCF(8):玩转消息协定

    Message翻译成中文,相信各位不陌生,是啊,就是消息,在WCF中也有消息这玩意儿,不知道你怎么去理解它.反正俺的理解,就像我们互发短信一个道理,通讯的双方就是服务器与客户端,说白了吧,就是二者之间 ...

  10. ida GDB 远程调试

    在看雪上回答的问题,有人问在WinDbg下断KiDebugRoutine或者KdEnterDebugger函数会引发蓝屏!因为是在调试Windows的内核调试引擎,我给出的解决办法是用不依赖Windo ...