在并发编程中,CAS算法和原子变量是实现并发控制的关键技术之一。本文将详细介绍CAS算法和原子变量的原理、使用方法和注意事项,包括它们的优点、缺点和适用范围。同时,本文还将利用代码案例介绍如何使用CAS算法和原子变量来解决并发问题。
CAS(Compare And Swap)算法是一种乐观锁技术,用于实现多线程并发控制。CAS操作包含三个操作数——内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。CAS在硬件层面保证了比较并交换操作的原子性。
CAS算法的优点在于它是一种无锁算法,可以在不使用锁的情况下实现并发控制。相比于传统的锁机制,CAS算法具有更高的并发性和性能。因为传统的锁机制需要将整个操作过程加锁,等待所有线程都完成后再释放锁,而CAS算法则可以在不使用锁的情况下实现并发控制。简单来说:
CAS算法是硬件对于并发操作共享数据的支持,一种无锁的非阻塞算法的实现,乐观锁算法。
CAS 包含了三个操作数
内存值 V
预估值 A
更新值 B
当且仅当 V == A 时,V=B,否则不做任何操作。
在java.util.concurrent.atomic包下面就是利用CAS算法保证变量原子性,通过查看代码CAS依靠的原生类Unsafe,存在sun.misc包,类方法用native修饰。这说明CAS是CPU指令级,只要我们安装了jdk,就实现,没法改变的。
主要还是ABA问题,这个后面有专讲分析,并如何解决。
原子变量是一种可以在不使用锁的情况下实现并发控制的数据结构。它提供了一些原子操作,比如原子加法、原子减法、原子取反等,这些操作都是不可分割的,即不会被其他线程打断。这使得原子变量可以在多线程环境下安全地使用。
Java中的java.util.concurrent.atomic包提供了许多原子变量类,比如AtomicInteger、AtomicLong、AtomicBoolean等。这些类中的方法都是用硬件级别的指令实现的,可以在不使用锁的情况下保证原子性。
我们都知道,在多线程环境下,使用volatile对共享变量进行叠加i++操作,会出现结果跟实际结果不一致,i++实际上分为“读-改-写”,实际是有这样的:
int temp = i;
i = i+1;
i = temp;
这样多线程同时操作,就有可能出现意想不到的结果。这种在多线程环境下,多个线程同时对同一个变量进行读写操作,可能会导致数据的不一致性,就是变量的原子性问题。
为了解决变量的原子性问题,可以采用以下几种方法:
为了保证变量原子性,使用加锁,肯定是可以解决,加锁使得每次只允许一个线程进行读写操作,但是无疑会减低程序性能,所以本次以Java中的java.util.concurrent.atomic包提供了许多原子变量类,比如AtomicInteger、AtomicLong、AtomicBoolean等。
在volatile多线程叠加的时候,继续模拟20个线程,每个线程叠加到100,我们修改变量为AtomicInteger类型,具体代码如下:
class MyData{
volatile int number = 0;
public void addTo60(){
this.number = 60;
}
//使用automic类
AtomicInteger atomicInteger = new AtomicInteger();
public void addAtomic(){
atomicInteger.getAndIncrement();
}
}
public class VolatileDemo {
public static void main(String[] args) {
MyData myData = new MyData();
for (int i = 0; i <= 20; i++) {
new Thread(()->{
for (int j = 0; j < 100; j++) {
myData.addPlusPlus();
myData.addAtomic();
}
},String.valueOf(i)).start();
}
// 需要等待上面所有子线层执行完毕之后,主线程在运行
// 如果当前线程大于2,说明还有子线程
while(Thread.activeCount() > 2){
Thread.yield();
}
System.out.println("volatile修饰结果:"+myData.number);
System.out.println("原子类AtomicInteger 结果:"+myData.atomicInteger);
}
}
运行结果:可以看到原子类AtomicInteger修饰的结果,才是正确的。
其实并发编程中,我们通常会遇到以下三个问题:原子性问题,可见性问题,有序性问题,通过这讲以及之前讲解的volatile变量,我们基本保证并发环境的原子性、可见性和有序性。解决的方式有很多种,也各只有优缺点,在实际的开发中,我们需要根据业务场景选择。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。