一、说明
- 1.被final关键字修饰,不能被继承
- 2.是sun.misc包下
- 3.Unsafe类不是表面上的线程是否安全的类,因为该类是底层,操作的是内存和线程,不建议编程人员直接使用
二、代码示例
package com.learning.atomic;
import lombok.Data;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
/**
* @Description Unsafe
*/
public class UnsafeLearning {
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(Teacher.class.getDeclaredField("id"));
long nameOffset = unsafe.objectFieldOffset(Teacher.class.getDeclaredField("name"));
Teacher teacher = new Teacher();
// 2.执行cas操作
unsafe.compareAndSwapInt(teacher, idOffset, 0, 1);
unsafe.compareAndSwapObject(teacher, nameOffset, null, "张三");
// 3.验证
System.out.println(teacher);
}
}
@Data
class Teacher{
volatile int id;
volatile String name;
}
package com.learning.atomic;
import lombok.extern.slf4j.Slf4j;
import sun.misc.Unsafe;
import java.util.LinkedList;
import java.util.List;
/**
* @Description 自定义的原子数据
*/
@Slf4j
public class AtomicData {
public static void main(String[] args) {
MyAtomicInteger account = new MyAtomicInteger(10000);
List<Thread> list = new LinkedList<>();
for (int i = 0; i < 1000; i++) {
list.add(new Thread(()->{
account.withdraw(10);
}));
}
long start = System.currentTimeMillis();
list.forEach(Thread::start);
list.forEach(t->{
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
long end = System.currentTimeMillis();
log.info("余额为:{}",account.getBalance());
log.info("耗时为:{}", end-start);
}
}
class MyAtomicInteger{
private volatile int value;
private static final long valueOffset;
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 previous = this.value;
int next = previous - amount;
if(UNSAFE.compareAndSwapInt(this, valueOffset, previous, next)){
break;
}
}
}
public MyAtomicInteger(int value){
this.value = value;
}
public Integer getBalance(){
return getValue();
}
public void withdraw(Integer amount){
decrement(amount);
}
}