++操作你还在使用加锁去保证线程的安全吗?确定不了解一下CAS机制?
Posted 你这家伙
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了++操作你还在使用加锁去保证线程的安全吗?确定不了解一下CAS机制?相关的知识,希望对你有一定的参考价值。
什么是CAS
CAS(Compare and swap),字面意思可以理解为“比较和交换”:
它其实就是假设内存中原有的数据为 V ,旧的预期值为 A 需要修改的值为 B,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。
当多个线程同时对某个资源进行CAS操作,只能有一个线程操作成功,但是并不会阻塞其他线程,其他线
程只会收到操作失败的信号。可见 CAS 其实是一个乐观锁。
通俗的将就是针对某个内存地址的内容,猜一下里面的值,如果猜对了,就将这个值更换成一个新的值,如果猜错了,就啥也不干(这一系列都是原子操作,而操作系统/硬件设备是赋予应用程序的一种进行原子操作的力量源泉之一)
话不多说,来看看下面这个例子
CAS的效率很高,有的时候为了实现线程的安全,同时又尽可能的提高效率,CAS往往是一种更好的选择(无锁编程)。
CAS的典型场景——无锁编程
无锁编程也是为了保证线程的安全,之前可能为了保证线程安全就会加锁,但是有的情况下加锁开销比较大(即便sychronized锁内置了很多的优化策略,但是还是比较大),所以这就要使用CAS
话不多说,在看例子
例如,想完成一个线程安全的 i++操作(CAS实现)
是不是看不懂,不要紧,咱给你画图解答
Atomic操作类(原子操作)
因为int long……等内置类型他的++操作或者–操作都不是原子操作,这是我们就可以使用java中的原子操作类,所谓的原子操作类本质上就是提供了原子的++或者–等操作(本质上就是对CAS进行了封装,然后提供了一组现成的类)
可以通过CAS实现在用户态实现轻量级锁/自旋锁
CAS缺点——ABA问题
首先什么是ABA问题:就是一个值从A变成了B又变成了A,而这个期间我们不清楚这个过程。
如何解决ABA问题呢?
答:既然要解决ABA问题,就需要引入额外的代价
给 i 这个变量关联一个“版本号”,每次修改,版本号就+1,就可以根据版本号来区分当前的是否被修改过了
以上是关于++操作你还在使用加锁去保证线程的安全吗?确定不了解一下CAS机制?的主要内容,如果未能解决你的问题,请参考以下文章