1、原子类
- 可以实现一些原子操作
- 基于CAS
下面就以AtomicInteger为例。
2、AtomicInteger
在没有AtomicInteger之前,对于一个Integer的线程安全操作,是需要使用同步锁来实现的,当然现在也可以通过ReentrantLock来实现,但是最好最方便的实现方式是采用AtomicInteger。
具体示例:
package com.collection.test;import java.util.concurrent.atomic.AtomicInteger;/*** 原子类的测试*/ public class AtomicTest {private static AtomicInteger atomicInteger = new AtomicInteger();//获取当前值public static void getCurrentValue(){System.out.println(atomicInteger.get());//-->0 }//设置value值public static void setValue(){atomicInteger.set(12);//直接用12覆盖旧值System.out.println(atomicInteger.get());//-->12 }//根据方法名称getAndSet就知道先get,则最后返回的就是旧值,如果get在后,就是返回新值public static void getAndSet(){System.out.println(atomicInteger.getAndSet(15));//-->12 }public static void getAndIncrement(){System.out.println(atomicInteger.getAndIncrement());//-->15 }public static void getAndDecrement(){System.out.println(atomicInteger.getAndDecrement());//-->16 }public static void getAndAdd(){System.out.println(atomicInteger.getAndAdd(10));//-->15 }public static void incrementAndGet(){System.out.println(atomicInteger.incrementAndGet());//-->26 }public static void decrementAndGet(){System.out.println(atomicInteger.decrementAndGet());//-->25 }public static void addAndGet(){System.out.println(atomicInteger.addAndGet(20));//-->45 }public static void main(String[] args) {AtomicTest test = new AtomicTest();test.getCurrentValue();test.setValue();//返回旧值系列 test.getAndSet();test.getAndIncrement();test.getAndDecrement();test.getAndAdd();//返回新值系列 test.incrementAndGet();test.decrementAndGet();test.addAndGet();} }
源代码:
private volatile int value;// 初始化值/*** 创建一个AtomicInteger,初始值value为initialValue*/public AtomicInteger(int initialValue) {value = initialValue;}/*** 创建一个AtomicInteger,初始值value为0*/public AtomicInteger() {}/*** 返回value*/public final int get() {return value;}/*** 为value设值(基于value),而其他操作是基于旧值<--get()*/public final void set(int newValue) {value = newValue;}public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}/*** 基于CAS为旧值设定新值,采用无限循环,直到设置成功为止* * @return 返回旧值*/public final int getAndSet(int newValue) {for (;;) {int current = get();// 获取当前值(旧值)if (compareAndSet(current, newValue))// CAS新值替代旧值return current;// 返回旧值 }}/*** 当前值+1,采用无限循环,直到+1成功为止* @return the previous value 返回旧值*/public final int getAndIncrement() {for (;;) {int current = get();//获取当前值int next = current + 1;//当前值+1if (compareAndSet(current, next))//基于CAS赋值return current;}}/*** 当前值-1,采用无限循环,直到-1成功为止 * @return the previous value 返回旧值*/public final int getAndDecrement() {for (;;) {int current = get();int next = current - 1;if (compareAndSet(current, next))return current;}}/*** 当前值+delta,采用无限循环,直到+delta成功为止 * @return the previous value 返回旧值*/public final int getAndAdd(int delta) {for (;;) {int current = get();int next = current + delta;if (compareAndSet(current, next))return current;}}/*** 当前值+1, 采用无限循环,直到+1成功为止* @return the updated value 返回新值*/public final int incrementAndGet() {for (;;) {int current = get();int next = current + 1;if (compareAndSet(current, next))return next;//返回新值 }}/*** 当前值-1, 采用无限循环,直到-1成功为止 * @return the updated value 返回新值*/public final int decrementAndGet() {for (;;) {int current = get();int next = current - 1;if (compareAndSet(current, next))return next;//返回新值 }}/*** 当前值+delta,采用无限循环,直到+delta成功为止 * @return the updated value 返回新值*/public final int addAndGet(int delta) {for (;;) {int current = get();int next = current + delta;if (compareAndSet(current, next))return next;//返回新值 }}/*** 获取当前值*/public int intValue() {return get();}
说明:使用与源代码都简单到爆了!自己看看注释。
注意:
- value是volatile的,关于volatile的相关内容见《附2 volatile》,具体链接:http://www.cnblogs.com/java-zhao/p/5125698.html
- 单步操作:例如set()是直接对value进行操作的,不需要CAS,因为单步操作就是原子操作。
- 多步操作:例如getAndSet(int newValue)是两步操作-->先获取值,在设置值,所以需要原子化,这里采用CAS实现。
- 对于方法是返回旧值还是新值,直接看方法是以get开头(返回旧值)还是get结尾(返回新值)就好
- CAS:比较CPU内存上的值是不是当前值current,如果是就换成新值update,如果不是,说明获取值之后到设置值之前,该值已经被别人先一步设置过了,此时如果自己再设置值的话,需要在别人修改后的值的基础上去操作,否则就会覆盖别人的修改,所以这个时候会直接返回false,再进行无限循环,重新获取当前值,然后再基于CAS进行加减操作。
- 如果还是不懂CAS,类比数据库的乐观锁。
补充一个东西:
1 // setup to use Unsafe.compareAndSwapInt for updates 2 private static final Unsafe unsafe = Unsafe.getUnsafe(); 3 private static final long valueOffset; 4 5 static { 6 try { 7 valueOffset = unsafe.objectFieldOffset 8 (AtomicInteger.class.getDeclaredField("value")); 9 } catch (Exception ex) { throw new Error(ex); } 10 } 11 12 private volatile int value;
这是AtomicInteger的所有属性,其中value存的是当前值,而当前值存放的内存地址可以通过valueOffset来确定。实际上是“value字段相对Java对象的起始地址的偏移量”
1 public final boolean compareAndSet(int expect, int update) { 2 return unsafe.compareAndSwapInt(this, valueOffset, expect, update); 3 }
CAS方法:通过对比“valueOffset上的value”与expect是否相同,来决定是否修改value值为update值。