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不一一说明了,因为用的不算太多。
上一篇:
通过多线程提高代码的执行效率例子
