【编程技巧】无锁并发之原子操作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 包含三个参数:

  1. 变量所在内存地址 V;
  2. 变量对应的值 A;
  3. 我们将要修改的值 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;
}
posted @ 2021-11-04 18:17  李柱明  阅读(400)  评论(0编辑  收藏  举报