本篇文章为你整理了CAS实现原理详解 – mikechen的互联网架构(cas原理分析)的详细内容,包含有cas机制的实现原理 cas原理分析 cas基本原理 cas的底层原理 CAS实现原理详解 – mikechen的互联网架构,希望能帮助你了解 CAS实现原理详解 – mikechen的互联网架构。
系统掌握 Java 多线程和并发编程的技术原理和知识点,写出优秀的并发代码
熟练应用各种并发工具,了解在什么情况下使用哪些具体的技术和方法
分掌握常见的多线程和并发问题分析技巧,知道排查一般问题的具体步骤
构建完整全面的并发编程知识体系,以及常见的面试问题和技巧
精通Java并发编程,彻底掌握 Java 并发编程知识。
详细内容
操作系统的发展历程
多线程、纤程、协程
硬件内存架构
并发和并行
CPU和高速缓存
缓存一致性
指令重排
支撑Java内存模型原理
Volatile的实现源码剖析
内存屏障
经典的单例的双重检测源码剖析
AQS的设计和结构
AQS源码深度剖析
线程通信与状态流转
Synchronized的实现原理及应用
Synchronized锁的膨胀升级过程分析
乐观锁、悲观锁、重入锁、公平锁、非公平锁及锁的粒度详解
ReentrantLock源码深度剖析与实战
可重入锁原理、获取锁和释放锁
ReentrantReadWriteLock源码深度剖析与实战
Condition 条件队列
线程池核心原理
线程池核心参数、拒绝策略、任务流程详解
线程池ThreadPollExecutor
阻塞与非阻塞队列详解
CountDownLatch源码深度剖析与实战
Semaphore源码深度剖析与实战
CyclicBarrier源码深度剖析与实战
ArrayBlockingQueue源码深度剖析
ConcurrentLinkedQueue 源码深度剖析
PriorityBlockingQueue 源码深度剖析
并发Atomic原子
死锁解决方案
CAS算法乐观锁
CAS的ABA问题
ThreadlLocal源码深度解析
ThreadlLocal数据隔离
ThreadlLocal内存溢出
ForkJoin原理解析
ConcurrentHashMap JDK1.8源码剖析
ArrayList、LinkedList、CopyOnWriteArrayList的实现原理
阻塞队列的实现原理与应用
非阻塞队列的实现原理与应用
ConcurrentLinkedQueue源码深度剖析
ArrayBlockingQueue源码深度剖析
深入LinkedBlockingQueue实现原理
反射泛型
从 0 掌握消息队列(MQ)的关键技术,了解核心知识
全面了解各类 MQ 技术的原理和特性,洞悉相关原理
深入理解 MQ 的特点和应用场景
掌握RabbitMQ RocketMQ Kafaka架构设计
全面吃透RocketMQ的源码底层实现
详细内容
消息队列的设计
消息队列的核心组成
消息队列的传输模式
消息队列的消费模式
消息队列的消息协议
消息队列的发送方式
消息队列的应用
异步调用的实现原理
应用解耦的实现原理
削峰填谷的实现原理
消息队列的架构与选型
Kafka的核心架构设计
RabbitMQ的核心架构设计
RocketMQ的核心架构设计
主流消息队列的选型与优劣比较
如何设计一个消息队列
消息队列的整体架构
消息队列的核心流程
消息队列传输过程
消息队列如何数据存储
消息队列如何做消息消费
同步异步编程
同步编程的实现
异步编程的实现
Future的源码剖析
同步、异步源码案例讲解
RocketMQ零拷贝
RocketMQ Mmap的实现
PageCache
Mmap的底层实现原理
虚拟内存
缺页中断
RocketMQ源码深度剖析
RocketMQ异步通信
RocketMQ核心存储
RocketMQ消费队列
精通分布式事务并对其原 理有深入理解
精通分布式锁、Session、全局唯一ID等并对其原 理有深入理解
掌握分布式数据库并对原理有深入理解
全面了解分布式的协议
全面了解分布式存储方案
详细内容
微服务架构变迁史
淘宝分布式架构演变过程
分布式协议
一致性模型
Gossip协议
Paxos协议
Raft协议
Zab协议
分布式Session解决方案
session
分布式session
分布式session方案
Session复制
Session存储在Cookie
Session粘性管理
Session集中管理在后端
分布式Session方案优劣势比较
分布式事务解决方案
分布式事务
BASE
一致性模型
XA两阶段
事务补偿TCC
消息队列最终一致性
分布式锁解决方案
分布式锁的由来
分布式锁的特点
分布式锁解决方案
数据库分布式锁
Redis分布式锁
Zookeeper分布式锁
分布式锁解决方案优劣势比较
分布式全局唯一ID
分布式全局唯一ID的要求
分布式全局唯一ID的方案
分布式全局唯一ID方案的优劣势比较
Snowflake雪花算法详解
大厂分布式全局唯一ID方案
分布式关系SQL数据库解决方案
SQL - NoSQL- NewSQL发展轨迹
MySQL+分库分表
Spanner
Aurora
NewSQL新型分布式数据库比较
分布式NoSQL数据库解决方案
NoSQL的三大基石
列式数据
文档数据库
图形数据库
内存键值数据库
主流NoSQL数据库比较
分布式文件存储解决方案
FastDFS
MogileFS
MooserFS
GlusterFS
Ceph
14:亿级高性能架构设计
在并发编程中,多线程竞争同一个资源时,一般我们常用的是synchronized等排它锁来解决多线程的资源竞争。
synchronized属于有锁的解决方案,但是加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题。
是否可以采用无锁的方式来解决多线程竞争?
CAS就是一个无锁解决方案,更准确的是采用乐观锁技术,但并不是说CAS的方式就是性能最好的,无锁也有它的劣势,文末会谈到它的劣势与应用场景。
为了助大家掌握好CAS,本节课我会重点讲解以下6点:
1.CAS
2.CAS的实现原理
3.CAS的优缺点
4.CAS自旋
5.CAS的ABA问题
6.CAS的总结
目录
什么是CASCAS的算法CAS的优缺点CAS的ABA问题CAS总结
什么是CAS
CAS(Compare and swap),即比较并交换,也是实现我们平时所说的自旋锁或乐观锁的核心操作。
Java并发包中的很多类都使用了CAS技术,是实现我们平时所说的自旋锁或乐观锁的核心操作。
CAS的算法
它的实现很简单,就是用一个预期的值和内存值进行比较,如果两个值相等,就用预期的值替换内存值,并返回 true。否则,返回 false。
CAS机制当中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B
更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B
CAS的实现原理
如上图显示,两个线程:线程1和线程2同时修改值,如果通过CAS来实现,具体流程如下:
在内存地址V当中,存储着值为7的变量
线程1想要把变量的值增加1,对线程1来说,旧的预期值A=7,要修改的新值B=8
线程2抢先一步,把内存值V修改:8
线程1开始提交更新,首先对比了预期值A=7和实际值V的比较8(Compare),发现A不等于V的实际值,提交失败
CAS的优缺点
1.CAS的优点
非阻塞的轻量级的乐观锁,通过CPU指令实现,在资源竞争不激烈的情况下性能高
2.CAS的三大缺点:
1)自旋(循环)时间过长,消耗CPU资源,如果资源竞争激烈,多线程自旋长时间消耗资源
2)只能保证一个共享变量的原子操作,不能保证代码块的原子性。比如需要保证3个变量共同进行原子性的更新,需要Synchronized解决。从Java1.5开始JDK提供了
3)AtomicReference类来保证引用对象之间的原子性,你可以把多个变量放在一个对象里来进行CAS操作。
CAS算法在JDK中的应用
在原子类变量中,如java.util.concurrent.atomic中的AtomicXXX,都使用了这些底层的JVM支持为数字类型的引用类型提供一种高效的CAS操作,而在java.util.concurrent中的大多数类在实现时都直接或间接的使用了这些原子变量类。
Java 中AtomicInteger.incrementAndGet()的实现源码为:
AtomicInteger:递增计数器实现
该方法采用了CAS操作,每次从内存中读取数据然后将此数据和+1后的结果进行CAS操作,如果成功就返回结果,否则重试直到成功为止。
CAS的ABA问题
线程1准备用CAS修改变量值A
在此之前,线程2将变量的值由A替换为B,又由B替换为A,然后线程1执行CAS时发现变量的值仍然为A,所以CAS成功,但实际上这时的现场已经和最初不同了。
解决方案
java的原子类AtomicStampedReference,通过控制变量值的版本号来保证CAS的正确性。具体解决思路就是在变量前追加上版本号,每次变量更新的时候把版本号加一,那么A B A就会变成1A 2B 3A。
CAS总结
基于CAS实现的乐观锁在低并发的情况下会比synchronized的效率高,因为不存在加锁解锁的操作。
但是在多并发的情况下,多个线程都在进行自旋,会导致cpu负载过高。
synchronized主要是在切换线程时会发生用户态和内核态的切换,也会导致消耗比较多的资源。
在使用的时候,如果并发量不大,推荐CAS锁。
CAS乐观锁,总是假设最好的情况,每次去读数据的时候都人为别人不会修改,所以不会上锁,但是在更新的时候
会判断一下在此期间有没有其他线程更新该数据。
悲观锁,总是假设最坏的情况,每次去读数据的时候都人为别人会修改,所以每次在读数据的时候都会上锁,这样别人想读取数据就会阻塞直到它获得锁。
乐观锁的缺点:
1、ABA问题
2、自旋时间长开销大
3、只能保证一个共享变量的原子操作
悲观锁的缺点:
1、需要独占资源,
2、会发生线程阻塞
3、线程之间切换会发费时间
乐观锁和悲观锁在部分场景下可以看做相对的两面,优缺点恰好是对照的,一个的缺点恰好是另一个的优点
乐观锁的悲观锁的优缺点决定了他们的适用场景
乐观锁适用于写比较少的情况下,在这种场景下用乐观锁可以省去锁的开销,加大系统的吞吐量
悲观锁适用于多写场景,在多写的情况下,一般会经常产生冲突,这时候用乐观锁会不断的进行自旋,反倒是降低了性能
资源竞争较少的场景,用乐观锁相比较于悲观锁,可以减少线程之间切换的时间
资源竞争严重的情况,CAS自旋的概率会比较大,从而浪费更多的CPU资源,效率低于悲观锁
1.CAS乐观锁,总是假设最好的情况,每次去读数据都认为别人不会修改,所以不会上锁,但更新的时候需要判断该数据是否被人修改过,如果被修改过,则不进行数据更新,如果没有被修改过,进行更新。
2.synchronized悲观锁,每次获取数据都担心被修改,所以每次获取数据都会进行加锁,使用完后会解锁。在加锁期间,其他对该数据进行读写的线程都会进行等待。
乐观锁适用于读多写少,并发冲突少的场景;悲观锁适合强一致性的场景,但效率比较低,特别是读的并发低。
对于资源竞争较少,可以使用乐观锁,因为CAS基于硬件实现,不会进入内核,不需要切换线程,操作自选几率较少,可以获得较高性能;而使用synchronized的悲观锁会进行线程阻塞和唤醒切换,用户态和内核态切换操作额外消费CPU资源。
对于资源竞争较多,CAS自旋的概率会比较大,从而浪费更多的CPU资源,效率低于synchronized;
但是在jdk1.6后,synchronized进行了优化,基于Lock-free的队列,基本思路是自旋后阻塞。在线程冲突较少的情况下,可以获得和CAS类似的性能;当线程冲突严重的请款改下,性能高于cas
以上就是CAS实现原理详解 – mikechen的互联网架构(cas原理分析)的详细内容,想要了解更多 CAS实现原理详解 – mikechen的互联网架构的内容,请持续关注盛行IT软件开发工作室。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。