原子类:
指具有原子操作特性的类。原子操作简而言之就是不可分割的操作,该操作在执行过程中不会被线程调度机制中断,从而保证了在多线程环境下操作的完整性和一致性。
原子类的作用:
是为了在并发情况下保证线程安全,原子类具有更高的力度和更好的性能。
原理与实现:
原子类通常利用CAS, compare and swap其比较并交换算法来实现其原子性。
CAS算法:
是一种基于硬件对并发操作的原语,它涉及到三个操作数,内存位置V,预期原值A,新值。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值,这个操作是原子的,意味着他要么完全执行,要么完全不执行,不会被其他线程打断。
在Java中,原子类被封装在java.util.concurrent.atomic包。AtomicInteger、AtomicLong、Atomic Reference等。这些类通过底层使用CAS算法和关键字volatile确保变量的可见性和禁止指令重排序来实现。
优点:
在高并发场景下,使用原子类的效率更高,因为原子类底层利用了CAS,不会阻塞线程,减少了线程上下文切换的开销。
使用场景:
原子类广泛应用于需要保证线程安全的并发编程场景中,如计数器、累加器。
会带来的问题:
1、ABA问题,CAS算法可能会遇到ABA问题,其变量的值从A变为B,然后又变为A,但算法会误认为他没有被修改过。
2、操作一直不成功,会导致自旋锁一直无法获取资源,从而占用CPU。长时间自旋会消耗大量的CPU资源。
CAS的ABA问题解决:
使用版本号或时间戳。类似于乐观锁,加个字段版本号,每个线程修改了版本号就加1。每次修改的时候比较一下版本号是否增加了,如果增加了就说明别的线程修改了。