并发包原子类详解
原子类型是一种无锁的、线程安全的、使用基本数据类型和引用数据类型的线程安全解决方案。
? ? ?CAS算法:CAS包含3个操作数,分别是内存值V、预期值A、要修改的新值B。当且仅当预期值A与内存值V相等时,将内存值V修改为B,否则什么都不需要做。
? ? ?借助CAS算法,并发包原子类对value的修改都是基于这种算法进行的,这种方式比synchronized、Lock等方式性能高很多。
1、AtomicInteger 详解
? ? ? AtomicInteger是Number类的一个子类,提供了很多原子性方法。在AtomicInteger内部有一个被volatile修饰的成员变量value,AtomicInteger提供的所有方法主要都是对value进行操作的,如+1、-1等。
? ? ?方法特别讲解:
? ? ? void lazySet(int newValue):在某些场景中,volatile的机制只会带来性能的拖累,这个时候使用此方法,性能比set方法高。在需要volatile内存屏障的情况下,与set方法等同。
? ? ? void set(int newValue):为value设置新值,因value被volatile修饰,可立即被其他线程看到。
2、AtomicBoolean详解
? ? 它是一种原子性读写布尔型变量的解决方案,通常情况下,该类被用作原子性地更新状态标志位。实现方式与AtomicInteger极为类似,AtomicBoolean内部的value也是一个被volatile修饰的int类型的属性。
3、AtomicLong详解
? ? AtomicLong提供了原子操作Long类型数据的解决方案,是Number类的子类,提供的原子性方法在使用习惯上与AtomicInteger非常一致。AtomicLong中基于CAS算法的实现比AtomicInteger的实现要复杂,主要原因是32位、64位CPU的支持程度不同。
4、AtomicReference
? ? AtomicReference提供了对象引用的非阻塞原子性读写操作,并且提供了一些高级用法。AtomicReference是一个泛型类,它的构造与其他原子类型的构造一样,也提供了无参和有参的构造函数。使用无参构造函数创建AtomicReference对象时,需要再次调用set方法为对象内部的value指定初始值。
? ? ?方法特别讲解:
? ? ?compareAndSet(V expect, V update):原子性地更新AtomicReference内部的value,其中expect代表当前的值,update代表新引用值。该方法返回一个boolean结果,如果expect和AtomicReference的当前值不相等,修改失败,返回false;若修改成功返回true。
——————————————————————————————————
AtomicInteger、AtomicBoolean、AtomicLong、AtomicReference,都采用了基于volatile关键字+CAS算法无锁的操作方式确保共享数据在多线程操作下的线程安全。
volatile关键字保证了线程间的可见性。
CAS算法,对比交换算法,提供了一种快速失败的方式,当某线程修改已经被改变的数据时会快速失败。
当CAS算法对共享数据操作失败时,因有自旋算法的加持,对共享数据的操作终究会完成。?
绝大多数情况下,原子类型自旋+CAS无锁操作保证了共享变量的线程安全和原子性。
——————————————————————————————————
5、AtomicStampedReference详解
? ? ?AtomicStampedReference在构建时需要一个类似于版本号的int类型变量stamped,解决了新值、旧值一致,更新后无法确认的情况。
? ? ?compareAndSet(V expectReference, V newReference, int expectedStamp, int newStamped):与其他原子类型的CAS算法类似,如果引用当前的值、版本号与expect的值、版本号一致,则将引用更新为新的值、版本号。
6、AtomicArray详解??
? ? 在Java的原子包中,提供了原子性操作数组元素的类,如:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray。
? ? 具体使用详见API
7、AtomicFieldUpdater详解
? ? ?要使共享数据的操作具备原子性,目前有两种方案:1、使用synchronized加锁;2、将对应的共享数据定义为原子类型。
? ? ? AtomicFieldUpdater提供除上述两种方案之外的第三种,原子性更新对象属性。目前并发包中有三种这样的类,分别为AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater。
? ? ? 使用时需要注意:1、未被volatile修饰的成员属性无法被原子性地更新;2、类的静态变量无法被原子性地更新;3、无法直接访问的成员属性不支持原子性地更新;final修饰的成员属性无法被原子性地更新;5、父类的成员属性无法被原子性地更新
? ? ? 这种方式更加节省内存,适用于第三方类库,,对类中某个属性提供原子性操作时。示例代码如下:
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
public class AtomicTest {
static class Demo{
volatile int salary;
public int getSalary() {
return this.salary;
}
}
public static void main(String[] args) {
AtomicIntegerFieldUpdater<Demo> updater=AtomicIntegerFieldUpdater.newUpdater(Demo.class, "salary");
Demo d=new Demo();
int result=updater.addAndGet(d, 10);
assert result==10;
}
}
8、sun.misc.Unsafe详解
? ? Unsafe帮助我们直接获得某个变量的内存偏移量,获取内存地址,在其内部更是运行了汇编指令,为高并发编程提供了Lock Free方案,提高并发程序的执行效率。但是Unsafe使用不当,造成的错误是灾难性的。获取Unsafe实例需要通过反射机制进行。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!