Java原子类Atomic原理和应用
jdk所提供的原子类可以大致分为四种类型:
- 原子更新基本数据类型
- 原子更新数组类型
- 原子更新抽象数据类型
- 原子更新字段
先来看看jdk提供的原子类(rt.jar包下java.util.concurrent.atomic):
首先我们来写一个数字自增生成器
package cn.itcats.thread.safe.Test1; public class Sequence { private int a = 0; public int add() { return a++; } public static void main(String[] args) { Sequence sequence = new Sequence(); new Thread(new Runnable() { public void run() { while (true) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " " + sequence.add()); } } }).start(); new Thread() { public void run() { while (true) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " " + sequence.add()); } }; }.start(); } }
列出部分的运行结果:
Thread-0 0 Thread-1 0 Thread-1 1 Thread-0 1 Thread-1 2 Thread-0 3 Thread-1 4 Thread-0 5
明显可见存在线程安全问题,这也就是我们正需要解决的问题
add()方法中 a++; 并不是一个原子性操作,我们使用原子类把int a变成一个原子类
package cn.itcats.thread.safe.Test1; import java.util.concurrent.atomic.AtomicInteger; public class Sequence { //使用原子类AtomicInteger private AtomicInteger a = new AtomicInteger(0); public int add() { return a.getAndIncrement(); //先获取再自增,对应a++ //若使用++a 则对应方法是a.incrementAndGet(); 先自增再获取 , //多说一句 a-- 就是 a.getAndDecrement(); //若a = a + 10;————对应API a.getAndAdd(10); } public static void main(String[] args) { Sequence sequence = new Sequence(); new Thread(new Runnable() { public void run() { while (true) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " " + sequence.add()); } } }).start(); new Thread() { public void run() { while (true) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " " + sequence.add()); } }; }.start(); } }
再看运行结果发现,并没有出现重复的数字。因此我们对数值的一些非原子性操作,都可以使用原子类转化为原子性操作。
除了对int等基本数据类型的操作,还可以对数组使用原子类进行原子性操作。
private int[] s = {1,2,3}; AtomicIntegerArray array = new AtomicIntegerArray(s); public int arrayAdd() { return array.getAndAdd(0, 10); }
对原子更新抽象数据类型进行设置和获取 AtomicReference<User> at = new AtomicReference<User>();
原子更新字段 如更新User字段属性
AtomicIntegerFieldUpdater<User> userAto = AtomicIntegerFieldUpdater.newUpdater(User.class,"name");
相关API不一一说明了,因为用的不算太多。
上一篇:
通过多线程提高代码的执行效率例子