【编程技巧】无锁并发之原子操作CAS
目录
前言
李柱明博客:https://www.cnblogs.com/lizhuming/p/15486895.html
一、什么是原子操作
不可被中断的一个或者一系列操作、
CAS 是 Compare And Set 的缩写,是以一种 无锁的方式实现并发控制 。在实际情况下,同时操作同一个对象的概率非常小,所以多数加锁操作做的是无用功, CAS 以一种乐观锁的方式实现并发控制 。
二、实现原子操作的方式
Java 可以通过锁和循环 CAS 的方式实现原子操作。
三、CAS( Compare And Swap ) 为什么要有 CAS?
Compare And Swap 就是比较并且交换的一个原子操作,由 Cpu 在指令级别上进行保证。
为什么要有 CAS:因为通过锁实现原子操作时,其他线程必须等待已经获得锁的线程运行完以后才能获得资源,这样就会占用系统的大量资源
四、CAS 包含哪些参数?
CAS 包含三个参数:
- 变量所在内存地址 V;
- 变量对应的值 A;
- 我们将要修改的值 B。
如果说 V 上的变量的值是 A 的话,就用 B 重新赋值,如果不是 A,那就什么事也不做,操作的返回结果原值是多少。
循环 CAS:在一个(死)循环【for(;😉】里不断进行 CAS 操作,直到成功为止(自旋操作即死循环)。
五、CAS 的原理
利用了现代处理器都支持的 CAS 的指令,循环这个指令,直到成功为止
六、CAS 实现原子操作的三大问题
1、 ABA 问题:其他的线程把值改成了 B ,很快改成了 A,原子操作的线程发现值是 A 就修改,这样会有问题。解决 ABA,引入版本号:1A->2C->3A
2、 循环时间很长的话,cpu 的负荷比较大
3、 对一个变量进行操作可以,同时操作多个共享变量有点麻烦
七、CAS 线程安全 ( 面试点 )
通过硬件层面的阻塞实现原子操作的安全
八、参考
- 数组实现线程安全的循环队列
/*
* cas函数如下:bool succ = __sync_bool_compare_and_swap(&a, b, c)
* ---》 if(a ==b ) {a = c;return true;}else{return false}
*/
struct queue{
int data[10000];
int front;
int back;
};
int maxSize=10000;
queue* q;
int push(int d)
{
if ((q->back+1)%maxSize==q->front)
return -1;
q->data[back]=d;
q->back=(q->back+1)%maxSize;
return 0;
}
int pop(int &d)
{
if(q->front==q->back) return -1;
d=q->data[q->front];
q->front=(q->front+1)%maxSize;
return 0;
}
// CAS
int pop2(int& d)
{
int temp=q->front;
if (temp==q->back)
return -1;
d=q->data[temp];
while(!__sync_bool_compare_and_swap(q->front,temp,(temp+1)%maxSize))
{
temp=(temp+1)%maxSize;
}
return 0;
}