Atomic、自旋锁、CAS
Atomic:是Java自带的一个包,该包中的类方便在多线程环境中,不使用锁的情况下进行原子操作。
其原理是采用了CAS+volatile+native方法进行实行,从而避免了使用锁,所以执行效率能够大步提升。
volatile:主要有两个功能:禁止重排序,保证了可见性(通过缓存一致性协议实现),Java并发中的原子性并没有去实现。
native:其实就是本地方法,由于Java的没有办法直接调用系统的资源,只有通过本地方法才能够调用,也就是通过C语言才能够实现,可以将native比作Java操作系统资源的后门。
有其几种分类:
1. 基本类型
2. 数组类型
3. 引用类型
基本类型:
1. AtomicInteger: 整型原子类
2. AtomicLong: 长整型原子类
3. AtomicBoolean: 布尔型原子类
数据类型:
1. AtomicIntegerArray: 整型数组原子类
2. AtomicLongArray: 长整型数组原子类
3. AtomicReferenceArray: 引用类型数组原子类
引用类型:
1. AtomicReference: 引用型原子类
2. AtomicStampedReference: 原子更新带有版本号的引用类型
3. AtomicMarkableReference: 原子更新带有标记位的引用类型
对象属性修改类型:
1. AtomicIntegerFieldUpdater: 原子更新整型字段的更新
2. AtomicLongFileldUpdater: 原子更新长整型字段的更新器
CAS(Compare and swap)比较和替换:
适用于Atomic中的类型,在多线程的工程中。是一条CPU并发原语。
是依赖于硬件的一种功能,通过多条连续的原语,来对一个数据进行操作,
所以说CAS是一条CPU原子指令,不会造成数据不一致。
原语:操作系统语言范畴,用于直接操作系统资源。
缺点:
1. 循环时间长,开销时间大,浪费CPU资源
2. 只能保证一个共享变量的操作
3. 可能会有ABA问题,假定一个数据是A,而修改之后数据为B,最后又修改为A,则当前线程的CAS操作无法辨认当前的数据A是否发生过变化
Unsafe:
是CAS的核心类,来自于rt.jar/sun/misc。
在不使用锁的情况下对数据进行读写,由于无法使用直接使用系统资源,所以只能使用系统的Unsafe类,一旦有方法使用 native 修饰,那么Java便无法直接只用该方法。而Unsafe相当于sun公司留的后门,可以直接操作特定内存的数据。
其内部的方法操作可以像C的指针一样操作内存,而比如像 AtomicInteger等数据,在多线程中不加锁的情况下可以实现不出错,是因为CAS在使用Unsafe的时候,通过对象在系统内存中的位置偏移地址,直接对系统内存地址中的数据执行了操作。
而且在最后所有的变量都会使用Volatile修饰,将其暴露给其他线程。
自旋锁:
在没有获得锁的情况下,反复去请求锁,期间可以做其他的事情,
其特点为非阻塞,浪费CPU资源
//简单原理
if(;;){
//请求某一资源 或者执行业务逻辑
User user = UserDao.getUser();
//成功则返回
if(user != null){
break;
}
//如果成功 一半都会睡一会儿,避免资源占用太高
Thread.sleep(10000);
}