并发包原子类详解

2023-12-13 09:48:03

原子类型是一种无锁的、线程安全的、使用基本数据类型和引用数据类型的线程安全解决方案。

? ? ?CAS算法:CAS包含3个操作数,分别是内存值V、预期值A、要修改的新值B。当且仅当预期值A与内存值V相等时,将内存值V修改为B,否则什么都不需要做。

? ? ?借助CAS算法,并发包原子类对value的修改都是基于这种算法进行的,这种方式比synchronized、Lock等方式性能高很多。

1、AtomicInteger 详解

? ? ? AtomicInteger是Number类的一个子类,提供了很多原子性方法。在AtomicInteger内部有一个被volatile修饰的成员变量value,AtomicInteger提供的所有方法主要都是对value进行操作的,如+1、-1等。

? ? ?方法特别讲解:

? ? ? void lazySet(int newValue):在某些场景中,volatile的机制只会带来性能的拖累,这个时候使用此方法,性能比set方法高。在需要volatile内存屏障的情况下,与set方法等同。

? ? ? void set(int newValue):为value设置新值,因value被volatile修饰,可立即被其他线程看到。

2、AtomicBoolean详解

? ? 它是一种原子性读写布尔型变量的解决方案,通常情况下,该类被用作原子性地更新状态标志位。实现方式与AtomicInteger极为类似,AtomicBoolean内部的value也是一个被volatile修饰的int类型的属性。

3、AtomicLong详解

? ? AtomicLong提供了原子操作Long类型数据的解决方案,是Number类的子类,提供的原子性方法在使用习惯上与AtomicInteger非常一致。AtomicLong中基于CAS算法的实现比AtomicInteger的实现要复杂,主要原因是32位、64位CPU的支持程度不同。

4、AtomicReference

? ? AtomicReference提供了对象引用的非阻塞原子性读写操作,并且提供了一些高级用法。AtomicReference是一个泛型类,它的构造与其他原子类型的构造一样,也提供了无参和有参的构造函数。使用无参构造函数创建AtomicReference对象时,需要再次调用set方法为对象内部的value指定初始值。

? ? ?方法特别讲解:

? ? ?compareAndSet(V expect, V update):原子性地更新AtomicReference内部的value,其中expect代表当前的值,update代表新引用值。该方法返回一个boolean结果,如果expect和AtomicReference的当前值不相等,修改失败,返回false;若修改成功返回true。

——————————————————————————————————

AtomicInteger、AtomicBoolean、AtomicLong、AtomicReference,都采用了基于volatile关键字+CAS算法无锁的操作方式确保共享数据在多线程操作下的线程安全。

volatile关键字保证了线程间的可见性。

CAS算法,对比交换算法,提供了一种快速失败的方式,当某线程修改已经被改变的数据时会快速失败。

当CAS算法对共享数据操作失败时,因有自旋算法的加持,对共享数据的操作终究会完成。?

绝大多数情况下,原子类型自旋+CAS无锁操作保证了共享变量的线程安全和原子性。

——————————————————————————————————

5、AtomicStampedReference详解

? ? ?AtomicStampedReference在构建时需要一个类似于版本号的int类型变量stamped,解决了新值、旧值一致,更新后无法确认的情况。

? ? ?compareAndSet(V expectReference, V newReference, int expectedStamp, int newStamped):与其他原子类型的CAS算法类似,如果引用当前的值、版本号与expect的值、版本号一致,则将引用更新为新的值、版本号。

6、AtomicArray详解??

? ? 在Java的原子包中,提供了原子性操作数组元素的类,如:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray。

? ? 具体使用详见API

7、AtomicFieldUpdater详解

? ? ?要使共享数据的操作具备原子性,目前有两种方案:1、使用synchronized加锁;2、将对应的共享数据定义为原子类型。

? ? ? AtomicFieldUpdater提供除上述两种方案之外的第三种,原子性更新对象属性。目前并发包中有三种这样的类,分别为AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater。

? ? ? 使用时需要注意:1、未被volatile修饰的成员属性无法被原子性地更新;2、类的静态变量无法被原子性地更新;3、无法直接访问的成员属性不支持原子性地更新;final修饰的成员属性无法被原子性地更新;5、父类的成员属性无法被原子性地更新

? ? ? 这种方式更加节省内存,适用于第三方类库,,对类中某个属性提供原子性操作时。示例代码如下:

import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

public class AtomicTest {
static class Demo{
volatile int salary;
public int getSalary() {
return this.salary;
}
}

public static void main(String[] args) {
AtomicIntegerFieldUpdater<Demo> updater=AtomicIntegerFieldUpdater.newUpdater(Demo.class, "salary");
Demo d=new Demo();
int result=updater.addAndGet(d, 10);
assert result==10;
}

}

8、sun.misc.Unsafe详解

? ? Unsafe帮助我们直接获得某个变量的内存偏移量,获取内存地址,在其内部更是运行了汇编指令,为高并发编程提供了Lock Free方案,提高并发程序的执行效率。但是Unsafe使用不当,造成的错误是灾难性的。获取Unsafe实例需要通过反射机制进行。

文章来源:https://blog.csdn.net/seacean2000/article/details/134946871
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。