AtomicInteger&无锁对象引用:AtomicReference

AtomicInteger介绍

AtomicInteger是一个提供原子操作的Integer类,通过线程安全的方式操作加减。

AtomicInteger使用场景

AtomicInteger提供原子操作来进行Integer的使用,因此十分适合高并发情况下的使用。

1.作为多个线程同时使用的原子计数器。

2.在比较和交换操作中实现非阻塞算法。

AtomicInteger作为原子计数器

要将其用作计数器,AtomicInteger类提供了一些方法来原子地执行加减运算。

1
2
3
4
5
6
addAndGet():以原子方式将给定值添加到当前值,并在添加后返回新值。
getAndAdd():以原子方式将给定值添加到当前值并返回旧值。
crementAndGet():以原子方式将当前值增加1,并在增加之后返回新值。 它等效于++ i操作。
getAndIncrement():以原子方式递增当前值并返回旧值。 它等效于i ++操作。
decrementAndGet():以原子方式将当前值减1,并在减后返回新值。 它等效于i-操作。
getAndDecrement():以原子方式减少当前值并返回旧值。 它等效于– -i操作。

AtomicInteger源码部分讲解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;

// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;

static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) {
throw new Error(ex);
}
}

private volatile int value;

以上为AtomicInteger中的部分源码,在这里说下其中的value,这里value使用了volatile关键字,volatile在这里可以做到的作用是使得多个线程可以共享变量,但是问题在于使用volatile将使得VM优化失去作用,导致效率较低,所以要在必要的时候使用,因此AtomicInteger类不要随意使用,要在使用场景下使用。

AtomicInteger的创建、塞值、取值

通过调用构造函数,可以直接创建AtomicInteger。 AtomicInteger提供了两种方法来获取和设置其实例的值。

1
2
3
4
5
6
7
8
9
//Initial value is 0
AtomicInteger atomicInteger=new AtomicInteger();

//Initial value is 100
AtomicInteger atomicInteger=new AtomicInteger(100);

int currentValue=atomicInteger.get(); //100

atomicInteger.set(1234); //Now value is 1234

AtomicInteger使用总结

AtomicInteger是在使用非阻塞算法实现并发控制,在一些高并发程序中非常适合,但并不能每一种场景都适合,不同场景要使用使用不同的数值类。

AtomicReference

1、使用场景:

解决并发修改多个属性

说到CAS理论,在java中我们第一个就想到了atomic类,一般常见的有AtomicInteger、AtomicBoolean等java.util.concurrent包下面的类,但是这个只能并发修改一个属性,如果我需要对多个属性同时进行并发修改,并且保证原子性呢?

AtomicReference和AtomicInteger非常类似,不同之处就在于AtomicInteger是对整数的封装,而AtomicReference则对应普通的对象引用,是操控多个属性的原子性的并发类。

业务场景:序列需要自增并且时间需要更新成最新的时间戳

2.简单介绍:

AtomicReference类提供了一个可以原子读写的对象引用变量。 原子意味着尝试更改相同AtomicReference的多个线程(例如,使用比较和交换操作)不会使AtomicReference最终达到不一致的状态。

3、实现原理:

1
2
3
4
5
6
private static final Unsafe unsafe = Unsafe.getUnsafe();
private volatile V value;

public AtomicReference(V initialValue) { value = initialValue; }

public final boolean compareAndSet(V expect, V update) { return unsafe.compareAndSwapObject(this, valueOffset, expect, update); }

AtomicReference的源码比较简单。它是通过”volatile”和”Unsafe提供的CAS函数实现”原子操作。

(01) value是volatile类型。这保证了:当某线程修改value的值时,其他线程看到的value值都是最新的value值,即修改之后的volatile的值。

(02) 通过CAS设置value。这保证了:当某线程池通过CAS函数(如compareAndSet函数)设置value时,它的操作是原子的,即线程在操作value时不会被中断。

4. 例子:

参考文章

评论