此文已由作者赵计刚授权网易云社区发布。
欢迎访问网易云社区,了解更多网易技术产品运营经验。
1、原子类
下面就以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;//当前值+1 if (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(); }
说明:使用与源代码都简单到爆了!自己看看注释。
注意:
补充一个东西:
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值。
免费领取验证码、内容安全、短信发送、直播点播体验包及云服务器等套餐
更多网易技术、产品、运营经验分享请点击。