zoukankan      html  css  js  c++  java
  • 读《Java并发编程的艺术》学习笔记(七)

    第7章  Java中的13个原子操作类

      当一个线程更新一个变量时,程序如果没有正确的同步,那么这个变量对于其他线程来说是不可见的。我们通常使用synchronized或者volatile来保证线程安全的更新共享变量。在JDK1.5中,提供了java.util.concurrent.atomic包,这个包中的原子操作类提供了一种用法简单,性能高效,线程安全地更新一个变量的方式。 

            Atomic包里一共提供了13个类,有4种类型的原子更新方式:原子更新基本类型、原子更新数组、原子更新引用和原子更新属性。其实现基本都是使用Unsafe实现的包装类。 

    7.1  原子更新基本类型类 
            - AtomicBoolean:原子更新布尔类型 

            - AtomicInteger:原子更新整型 

            - AtomicLong:原子更新长整型 

            以上3个类提供的方法基本一致,我们以AtomicInteger为例进行分析。 

        AtomicInteger常用的方法有: 

            - int addAndGet(int delta):以原子方式将输入的数值与实例中的值相加,并返回结果。 

            - boolean compareAndSet(int expect,int upate):如果输入的数值等于预期值,则以原子方式将该值设置为输入的值。 

            - int getAndIncrement():以原子方式将当前值加1,返回自增前的值。 

            - void lazySet(int newValue):最终会设置成new Value,但可能导致其他线程在之后的一小段时间内还是可以读到旧的值。 

            - int getAndSet(int newValue):以原子方式设置为newValue,并返回旧值。

        其实现依靠我们熟悉的CAS算法: 

      在Java的基本类型中除了Atomic包中提供原子更新的基本类型外,还由char、float和double。那么这些在Atomic包中没有提供原子更新的基本类型怎么保证其原子更新呢? 

            从AtomicBoolean源码中我们可以得到答案:首先将Boolean转换为整型,然后使用comareAndSwapInt进行CAS,所以原子更新char、float、double同样可以以此实现。

    7.2  原子更新数组 
            - AtomicIntegerArray:原子更新整型数组里的元素。 

            - AtomicLongArray:原子更新长整型数组里的元素。 

            - AtomicReferenceArray:原子更新引用类型数组里的元素。 

        【备注:】看书上说原子更新数组有4个类,除了上述3个外,还有AtomicBooleanArray类,但我在jdk5/6/7/8中都没有找到这个类的存在,只找到共12个原子操作类,而不是标题中的13个。不知道是否是书中的错误?请知情的童鞋不吝赐教。

        AtomicIntegerArray类主要提供原子的方式更新数组里的整型,其常用方法如下: 

            - int addAndGet(int i,int delta):以原子方式将输入值与数组中索引i的元素相加。 

            - boolean compareAndSet(int i,int expect,int update):如果当前值等于预期值,就把索引i的元素设置成update值。 

    【备注】:在AtomicIntegerArray构造方法中,AtomicIntegerArray会将数组复制一份,所以当其对内数组元素进行修改时,不会影响原传入数组。 

    7.3  原子更新引用类型 
            原子更新基本类型的AtomicInteger,只能更新一个变量,如果需要原子更新多个变量,就需要使用这个原子更新引用类型提供的类。Atomic包提供以下3个类: 

            - AtomicReference:原子更新引用变量。 

            - AtomicReferenceFieldUpdater:原子更新引用类型里的字段。 

            - AtomicMarkableReference:原子更新带有标记位的引用类型 。可以原子更新一个布尔类型的标记位和引用类型。构造方法时AtomicMarkableReference(V initialRef,boolean initialMark)。

    7.4  原子更新字段类 
            如果需要原子的更新某个类里的某个字段,就需要使用原子更新字段类,Atomic包提供了以下3个类进行原子字段更新: 

            - AtomicIntegerFieldUpdater:原子更新整型的字段的更新器。 

            - AtomicLongFiledUpdater:原子更新长整型字段的更新器。 

            - AtomicStampedReference:原子更新带有版本号的引用类型。该类将整数值与引用关联起来,用于原子的更新数据和数据的版本号,避免CAS的ABA问题、 

            想要原子的更新字段类需要调用静态方法newUpdater()创建一个更新器,并设置想要更新的类和属性。且更新类的字段必须使用public volatile修饰符。

  • 相关阅读:
    [置顶] location.href你真的会用了?
    Hive HA使用说明
    十进制转换为任意进制及操作符重载
    《重构》学习总结
    linux kill进程和子进程小trick
    express for node 路由route几种实现方式的思考
    BEGINNING SHAREPOINT® 2013 DEVELOPMENT 第2章节--SharePoint 2013 App 模型概览 总结
    Can rename table but can not truncate table
    HBase
    链表解说和基本操作练习附代码
  • 原文地址:https://www.cnblogs.com/mYunYu/p/12973059.html
Copyright © 2011-2022 走看看