用Unsafe实现AtomicInteger类
原理
AtomicInteger可以在并发情况下达到原子化更新,避免使用了synchronized,而且性能非常高。
AtomicInteger的底层是用Unsafe来实现的,这里我们手写一个AtomicInteger类,并且测试一下。
测试例子
启动 1000 个线程,每个线程做 -10 元 的操作,如果初始余额为 10000 那么正确的结果应当是 0。
以下代码在JDK1.8通过测试。
账户Account 类
interface Account {
// 获取余额
Integer getBalance();
// 取款
void withdraw(Integer amount);
/**
* 方法内会启动 1000 个线程,每个线程做 -10 元 的操作
* 如果初始余额为 10000 那么正确的结果应当是 0
*/
static void demo(Account account) {
List<Thread> ts = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
ts.add(new Thread(() -> {
account.withdraw(10);
}));
}
long start = System.nanoTime();
ts.forEach(Thread::start);
ts.forEach(t -> {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
long end = System.nanoTime();
System.out.println(account.getBalance()
+ " cost: " + (end-start)/1000_000 + " ms");
}
}
Account 实现类
class DiyAccount implements Account {
private DiyAtomicInteger balance;
public DiyAccount(int balance) {
this.balance = new DiyAtomicInteger(balance);
}
@Override
public Integer getBalance() {
return balance.getValue();
}
@Override
public void withdraw(Integer amount) {
balance.decrement(amount);
}
}
DiyAtomicInteger 类
class DiyAtomicInteger {
private volatile int value; //实例操作的变量
private static final long valueOffset;//偏移量
private static final Unsafe UNSAFE;// unsafe实例对象
static {
UNSAFE = UnsafeAccessor.getUnsafe();
try {
valueOffset = UNSAFE.objectFieldOffset(DiyAtomicInteger.class.getDeclaredField("value"));
} catch (NoSuchFieldException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public int getValue() {
return value;
}
public void decrement(int amount) {
while (true) {
int prev = this.value;
int next = prev - amount;
if (UNSAFE.compareAndSwapInt(this, valueOffset, prev, next)) {
break;
}
}
}
public DiyAtomicInteger(int value) {
this.value = value;
}
}
测试
public class Test {
public static void main(String[] args) {
Account account = new DiyAccount(10000);
Account.demo(account);
}
}
输出
0 cost: 65 ms
其它——Unsafe工具类UnsafeAccessor
我们知道Unsafe
的构造方法是私有的,也没有get
方法可以获取对象,所以我们只能通过反射的方式来实例化Unsafe
对象。
public final class Unsafe {
private static final Unsafe theUnsafe;
private Unsafe() {
}
...
}
所以
import sun.misc.Unsafe;
import java.lang.reflect.Field;
public class UnsafeAccessor {
private static final Unsafe unsafe;
static {
try {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
unsafe = (Unsafe) theUnsafe.get(null);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new Error(e);
}
}
public static Unsafe getUnsafe() {
return unsafe;
}
}
项目代码