Java多线程系列(四)—CAS操作和Automic原子类
由于线程安全需要保证原子性和可见性,而volatile关键字修饰的变量仅能保证可见性不能保证原子性,因此像i++这种非原子操作就是非线程安全的;为了保证原子性,JDK引入了原子操作类,放在在java.util.concurrent.automic包下;
Automic原子类底层是通过CAS实现,线程的重试会造成效率较低,JDK8引入了LongAdder和DoubleAdder类通过空间换时间的思想提高并发性能;
个人主页:tuzhenyu’s page
原文地址:Java多线程系列(四)—CAS操作和Automic原子类
(1)CAS操作
1.CAS的定义
CAS是乐观锁思想的一种实现,是为了保证一组比较替换操作原子性;当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败, 失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。
CAS乐观锁的实现与悲观锁的区别在于当资源不用的时候悲观锁会将线程挂起而CAS会继续重试直到资源可用;
2.CAS存在的问题(ABA)
CAS操作是进行比较替换,容易出现ABA问题;如果一个变量的初始值是A,一个线程准备将A改为了B,在这期间又有其他线程将A改回了B,又将B改回A,这个时候CAS会认为中间没有发生变化,实际上是已经是不同的这就出现了ABA问题;
ABA问题的解决办法:JDK引入了解决ABA问题的Automic原子类AutomicStampedReference,使用时间戳版本号来进行标记;
在高并发的情况下会出现CAS频繁碰撞,碰撞会造成赋值失败继续重试,越多线程重试,CAS失败几率又越高,变成恶性循环,造成效率底下等问题;
(2)Automic原子类
1. 原子操作类分类
基本类型:AtomicInteger AtomicLong AtomicBoolean
数组类型:AtomicIntegerArray AtomicLongArray AtomicReferenceArray
引用类型:AtomicReferece AtomicStampedRerence AtomicMarkableReference
对象的属性修改类型:AtomicIntegerFieldUpdater AtomicLongFieldUpdater AtomicReferenceFieldUpdater