1、java中的原子性操作
所谓原子性操作,是指执行一系列操作时,这些操作要么全部执行,要么全部不执行,不存在只执行其中一部分的情况。
2、CAS方法
CAS即Compare and Swap,其是JDK提供的非阻塞原子性操作,它通过硬件保证了比较-更新操作的原子性。CAS有四个操作数,分别为:对象内存地址、对象中的变量的偏移量、变量预期值和新的值。其操作含义为:如果对象obj中内存偏移量为valueOffset的变量为expect,则使用新的值update替换旧的值expect。也就是说,更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。这是处理器提供的一个原子性指令。
3、ABA问题
比如说一个线程one从内存位置V中取出A,这时候另一个线程two也从内存中取出A,并且two进行了一些操作变成了B,然后two又将V位置的数据变成A,这时候线程one进行CAS操作发现内存中仍然是A,然后one操作成功。
尽管线程one的CAS操作成功,但是不代表这个过程就是没有问题的。
4、Unsafe类
getUnsafe方法源码:
java"> @CallerSensitive
public static Unsafe getUnsafe() {
Class<?> caller = Reflection.getCallerClass();
if (!VM.isSystemDomainLoader(caller.getClassLoader()))
throw new SecurityException("Unsafe");
return theUnsafe;
}
- VM.isSystemDomainLoader(caller.getClassLoader()):这里判断是不是Bootstrap加载器加载了TestUnSafe.class。如果没有这个限制,那么我们的应用程序就可以随意使用Unsafe做事情了,而Unsafe类可以直接操作内存,这是不安全的,所以JDK开发组特意做了这个限制,不让开发人员再正规渠道使用Unsafe类,而是在rt.jar包里面的核心类中使用Unsafe功能。
我们可以使用万能的反射来获取Unsafe实例方法:
java">public class UnSafeTest2 {
static final Unsafe unsafe;
static final long stateOffset;
private volatile long state = 0;
static {
try {
// 使用反射获取Unsafe的成员变量theUnsafe
Field field = Unsafe.class.getDeclaredField("theUnsafe");
// 设置为可存取
field.setAccessible(true);
// 获取该变量的值
unsafe = (Unsafe) field.get(null);
// 获取state在UnsafeTest2中的偏移量
stateOffset = unsafe.objectFieldOffset(UnSafeTest2.class.getDeclaredField("state"));
}catch (Exception e) {
System.out.println(e.getLocalizedMessage());
throw new Error(e);
}
}
public static void main(String[] args) {
UnSafeTest2 test2 = new UnSafeTest2();
Boolean flag = unsafe.compareAndSwapInt(test2, stateOffset, 0, 1);
System.out.println(flag);
}
}