CAS
1、什么是CAS?
CAS:Compare and Swap,即比较再交换。
jdk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronouse同步锁的一种乐观锁。JDK 5之前Java语言是靠synchronized关键字保证同步的,这是一种独占锁,也是悲观锁
ABA
假设这里有两个线程线程1和线程2,线程1工作时间需要10秒,线程2工作需要2秒,主内存值为A,第一轮线程1和线程2都把A拿到自己的工作内存,2秒中后线程2工作完成把A改成了B再写回去,又过了2秒,线程2把B改成了A再写回去,然后就线程2进入休眠状态,这时候线程1工作完成,看到期望为A真实值也是A认为没有人动过,然后线程1进行CAS操作。尽管线程1的CAS操作成功,但是不代表这个过程就是没问题的。
ABA问题的解决
新增一种机制,那就是修改版本号(类似于时间戳)。
用AtomicStampedReference(int initialRef, int initialStamp),它有两个参数,第一个初始值,第二是初始版本号,它的compareAndSet方法有四个参数:
UnSafe
Java无法直接访问底层操作系统,而是通过本地(native)方法来访问。不过尽管如此,JVM还是开了一个后门,JDK中有一个类Unsafe,它提供了硬件级别的原子操作。
这个类尽管里面的方法都是public的,但是并没有办法使用它们,JDK API文档也没有提供任何关于这个类的方法的解释。总而言之,对于Unsafe类的使用都是受限制的,只有授信的代码才能获得该类的实例,当然JDK库里面的类是可以随意使用的。
Unsafe提供了硬件级别的操作,比如说获取某个属性在内存中的位置,比如说修改对象的字段值,即使它是私有的。不过Java本身就是为了屏蔽底层的差异,对于一般的开发而言也很少会有这样的需求。
//方法可以用来获取给定的f的内存地址偏移量,这个值对于给定的field是唯一的且是固定不变的。
private native long staticFieldOffset0(Field f);
//获取数组第一个元素的偏移地址
private native int arrayBaseOffset0(Class<?> arrayClass);
//获取数组的转换因子即数组中元素的增量地址的
private native int arrayIndexScale0(Class<?> arrayClass);
//下面三个方法
private native long allocateMemory0(long bytes);//分配内存
private native long reallocateMemory0(long address, long bytes);//扩充内存
private native void freeMemory0(long address);//释放内存