Unsafe提供了非常底层的,操作内存,线程的方法.Unsafe对象不能直接调用,只能通过反射获得.
import lombok.Data;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
public class TestUnsafe {
public static void main(String[] args) throws Exception {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unsafe = (Unsafe)theUnsafe.get(null);
System.out.println(unsafe);
// 1. 获取域的偏移地址
long idOffset = unsafe.objectFieldOffset(Student.class.getDeclaredField("id"));
long nameOffset = unsafe.objectFieldOffset(Student.class.getDeclaredField("name"));
Student student = new Student();
System.out.println(student);
// 2. 执行cas操作
unsafe.compareAndSwapInt(student,idOffset,0,1);
unsafe.compareAndSwapObject(student,nameOffset,null,"小明");
// 3. 验证
System.out.println(student);
}
}
@Data
class Student{
volatile int id;
volatile String name;
}
使用Unsafe构建自己的原子类
import sun.misc.Unsafe;
import java.util.ArrayList;
import java.util.List;
public class TestMyAtomicInteger {
public static void main(String[] args) {
Account.demo(new MyAtomicInteger(10000));
}
}
class MyAtomicInteger implements Account{
private volatile int value; // 使用cas,必须是volatile
private static final long valueOffset; // 获取域的偏移量
private static final Unsafe UNSAFE;
static{
UNSAFE = UnsafeAccessor.getUnsafe();
try {
valueOffset = UNSAFE.objectFieldOffset(MyAtomicInteger.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 MyAtomicInteger(int value){
this.value = value;
}
@Override
public int getBalance() {
return value;
}
@Override
public void withdraw(int amount) {
decrement(amount);
}
}
interface Account{
// 设置余额
int getBalance();
void withdraw(int amount);
static void demo(Account account){
List<Thread> ts = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
// 创建1000个线程,每个线程减去10
ts.add(new Thread(()->{
account.withdraw(10);
}));
}
ts.forEach(Thread::start);
ts.forEach(t->{
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println(account.getBalance());
}
}
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 (Exception e) {
throw new Error(e);
}
}
public static Unsafe getUnsafe(){
return unsafe;
}
}