1. 程式人生 > >JDK1.8的Java.util.concurrent.atomic包小結

JDK1.8的Java.util.concurrent.atomic包小結

Atomic意為原子的,JUC包又是併發包,所以不必多說。

Atomic的特點

①多執行緒環境下,無所的進行原子操作。
②不能絕對保證執行緒不被阻塞。(因不同CPU的原子指令不同,可能需要某種形式的內部鎖)

Atomic下有哪些類

13個實現類:

AtomicBoolean

@since 1.5

/**
 * A {@code boolean} value that may be updated atomically. See the
 * {@link java.util.concurrent.atomic} package specification for
 * description of the properties of atomic variables. An
 * {@code
AtomicBoolean} is used in applications such as atomically * updated flags, and cannot be used as a replacement for a * {@link java.lang.Boolean}. * * @since 1.5 * @author Doug Lea */
自己翻譯: 一、可能以原子方式更新。 二、不能當作Boolean的替代品

AtomicInteger

@since 1.5

 However, this class does extend
{@code
Number} to allow uniform access by tools and utilities that deal with numerically-based classes. 特點: 自己翻譯: 一、可能以原子方式更新。 二、不能當作Integer的替代品 三、類繼承自Number,允許被以數值為基礎的 classes檔案 當做工具類去使用

AtomicIntegerArray

@since 1.5

特點:
自己翻譯: 可能以原子方式更新。

這個類通常被用作

AtomicLong

@since 1.5

特點:
自己翻譯: 一、可能以原子方式更新。 二、不能當作Long的替代品 三、類繼承自Number,允許被以數值為基礎的 classes檔案 當做工具類去使用

AtomicLongArray

@since 1.5

特點:
自己翻譯: 可能以原子方式更新。

這個類通常被用作

AtomicMarkableReference


@since 1.5

/**
 * An {@code AtomicMarkableReference} maintains an object reference
 * along with a mark bit, that can be updated atomically.
 *
 * <p>Implementation note: This implementation maintains markable
 * references by creating internal objects representing "boxed"
 * [reference, boolean] pairs.
 *
 * @since 1.5
 * @author Doug Lea
 * @param <V> The type of object referred to by this reference
 */

一、維護一個物件引用,加上一個標記位,除了標記位外,還可以進行原子更新。
二、該實現通過建立表示“裝箱”(引用、布林)對的內部物件來保持標記引用。

AtomicReference

@since 1.5

一、可以以原子方式更新的物件引用

AtomicReferenceArray

@since 1.5
一、可以以原子方式更新的物件引用

AtomicStampedReference

@since 1.5

一、保持一個物件引用和一個整數“戳記”,可以以原子的方式更新。
二、實現說明:這個實現通過建立表示“裝箱”(引用、整數)對的內部物件來維護標記引用。

DoubleAccumulator

@since 1.8

/**
 * One or more variables that together maintain a running {@code double}
 * value updated using a supplied function.  When updates (method
 * {@link #accumulate}) are contended across threads, the set of variables
 * may grow dynamically to reduce contention.  Method {@link #get}
 * (or, equivalently, {@link #doubleValue}) returns the current value
 * across the variables maintaining updates.
 *
 * <p>This class is usually preferable to alternatives when multiple
 * threads update a common value that is used for purposes such as
 * summary statistics that are frequently updated but less frequently
 * read.
 *
 * <p>The supplied accumulator function should be side-effect-free,
 * since it may be re-applied when attempted updates fail due to
 * contention among threads. The function is applied with the current
 * value as its first argument, and the given update as the second
 * argument.  For example, to maintain a running maximum value, you
 * could supply {@code Double::max} along with {@code
 * Double.NEGATIVE_INFINITY} as the identity. The order of
 * accumulation within or across threads is not guaranteed. Thus, this
 * class may not be applicable if numerical stability is required,
 * especially when combining values of substantially different orders
 * of magnitude.
 *
 * <p>Class {@link DoubleAdder} provides analogs of the functionality
 * of this class for the common special case of maintaining sums.  The
 * call {@code new DoubleAdder()} is equivalent to {@code new
 * DoubleAccumulator((x, y) -> x + y, 0.0)}.
 *
 * <p>This class extends {@link Number}, but does <em>not</em> define
 * methods such as {@code equals}, {@code hashCode} and {@code
 * compareTo} because instances are expected to be mutated, and so are
 * not useful as collection keys.
 *
 * @since 1.8
 * @author Doug Lea
 */

一個或多個變數,共同維護一個執行的{@ code double}值,使用提供的函式更新。當更新(方法{@ link #積累})線上程之間進行爭用時,變數集可以動態增長以減少爭用。方法{@ link # get}(或者,相當地,{@ link # doubleValue})返回當前的值,以保持更新。
當多個執行緒更新一個共同的值時,這個類通常比其他方法更可取,比如經常更新但不經常讀取的彙總統計資訊。
提供的累加器函式應該是無副作用的,因為在嘗試更新失敗時,由於執行緒之間的爭用,它可能會被重新應用。函式以當前值作為其第一個引數,而給定的update作為第二個引數。例如,為了維持一個執行最大值,您可以提供{@ code Double::max}和{@ code Double。NEGATIVE_INFINITY }的身份。線上程內部或跨執行緒中積累的順序沒有保證。因此,這
如果需要數值穩定性,則類可能不適用,特別是當組合了大量不同的值時
的大小。類{@ link DoubleAdder}為維護和的共同特殊情況提供了該類的類似功能。呼叫{@ code新的DoubleAdder()}相當於{@ code new double累加器((x,y)- > x + y,0.0)}。
這個類擴充套件了{@ link Number},但是< em >不是< /em >定義了諸如{@ code =}、{@ code hashCode}和{@ code compareTo}之類的方法,因為例項被期望發生突變,因此不作為集合鍵有用。

DoubleAdder

@since 1.8

/**
 * One or more variables that together maintain an initially zero
 * {@code double} sum.  When updates (method {@link #add}) are
 * contended across threads, the set of variables may grow dynamically
 * to reduce contention.  Method {@link #sum} (or, equivalently {@link
 * #doubleValue}) returns the current total combined across the
 * variables maintaining the sum. The order of accumulation within or
 * across threads is not guaranteed. Thus, this class may not be
 * applicable if numerical stability is required, especially when
 * combining values of substantially different orders of magnitude.
 *
 * <p>This class is usually preferable to alternatives when multiple
 * threads update a common value that is used for purposes such as
 * summary statistics that are frequently updated but less frequently
 * read.
 *
 * <p>This class extends {@link Number}, but does <em>not</em> define
 * methods such as {@code equals}, {@code hashCode} and {@code
 * compareTo} because instances are expected to be mutated, and so are
 * not useful as collection keys.
 *
 * @since 1.8
 * @author Doug Lea
 */

一個或多個變數一起維護一個初始的零{@ code double} sum。當更新(方法{@ link # add})線上程之間進行爭用時,變數集可以動態增長以減少爭用。方法{@ link # sum}(或者,等價{@ link # doubleValue})將當前的總數組合在維持總和的變數上。線上程內部或跨執行緒中積累的順序沒有保證。因此,如果需要數值穩定性,這個類可能不適用,特別是當組合了大量不同數量級的值時。
當多個執行緒更新一個共同的值時,這個類通常比其他方法更可取,比如經常更新但不太頻繁的彙總統計資料
這個類擴充套件了{@ link Number},但是< em >不是< /em >定義了諸如{@ code =}、{@ code hashCode}和{@ code compareTo}之類的方法,因為例項被期望發生突變,因此不作為集合鍵有用。

LongAccumulator


@since 1.8

/**
 * One or more variables that together maintain a running {@code long}
 * value updated using a supplied function.  When updates (method
 * {@link #accumulate}) are contended across threads, the set of variables
 * may grow dynamically to reduce contention.  Method {@link #get}
 * (or, equivalently, {@link #longValue}) returns the current value
 * across the variables maintaining updates.
 *
 * <p>This class is usually preferable to {@link AtomicLong} when
 * multiple threads update a common value that is used for purposes such
 * as collecting statistics, not for fine-grained synchronization
 * control.  Under low update contention, the two classes have similar
 * characteristics. But under high contention, expected throughput of
 * this class is significantly higher, at the expense of higher space
 * consumption.
 *
 * <p>The order of accumulation within or across threads is not
 * guaranteed and cannot be depended upon, so this class is only
 * applicable to functions for which the order of accumulation does
 * not matter. The supplied accumulator function should be
 * side-effect-free, since it may be re-applied when attempted updates
 * fail due to contention among threads. The function is applied with
 * the current value as its first argument, and the given update as
 * the second argument.  For example, to maintain a running maximum
 * value, you could supply {@code Long::max} along with {@code
 * Long.MIN_VALUE} as the identity.
 *
 * <p>Class {@link LongAdder} provides analogs of the functionality of
 * this class for the common special case of maintaining counts and
 * sums.  The call {@code new LongAdder()} is equivalent to {@code new
 * LongAccumulator((x, y) -> x + y, 0L}.
 *
 * <p>This class extends {@link Number}, but does <em>not</em> define
 * methods such as {@code equals}, {@code hashCode} and {@code
 * compareTo} because instances are expected to be mutated, and so are
 * not useful as collection keys.
 *
 * @since 1.8
 * @author Doug Lea
 */

LongAdder

@since 1.8
/**
 * One or more variables that together maintain an initially zero
 * {@code long} sum.  When updates (method {@link #add}) are contended
 * across threads, the set of variables may grow dynamically to reduce
 * contention. Method {@link #sum} (or, equivalently, {@link
 * #longValue}) returns the current total combined across the
 * variables maintaining the sum.
 *
 * <p>This class is usually preferable to {@link AtomicLong} when
 * multiple threads update a common sum that is used for purposes such
 * as collecting statistics, not for fine-grained synchronization
 * control.  Under low update contention, the two classes have similar
 * characteristics. But under high contention, expected throughput of
 * this class is significantly higher, at the expense of higher space
 * consumption.
 *
 * <p>LongAdders can be used with a {@link
 * java.util.concurrent.ConcurrentHashMap} to maintain a scalable
 * frequency map (a form of histogram or multiset). For example, to
 * add a count to a {@code ConcurrentHashMap<String,LongAdder> freqs},
 * initializing if not already present, you can use {@code
 * freqs.computeIfAbsent(k -> new LongAdder()).increment();}
 *
 * <p>This class extends {@link Number}, but does <em>not</em> define
 * methods such as {@code equals}, {@code hashCode} and {@code
 * compareTo} because instances are expected to be mutated, and so are
 * not useful as collection keys.
 *
 * @since 1.8
 * @author Doug Lea
 */

4個抽象類
AtomicIntegerFieldUpdater

@since 1.5
/**
 * A reflection-based utility that enables atomic updates to
 * designated {@code volatile int} fields of designated classes.
 * This class is designed for use in atomic data structures in which
 * several fields of the same node are independently subject to atomic
 * updates.
 *
 * <p>Note that the guarantees of the {@code compareAndSet}
 * method in this class are weaker than in other atomic classes.
 * Because this class cannot ensure that all uses of the field
 * are appropriate for purposes of atomic access, it can
 * guarantee atomicity only with respect to other invocations of
 * {@code compareAndSet} and {@code set} on the same updater.
 *
 * @since 1.5
 * @author Doug Lea
 * @param <T> The type of the object holding the updatable field
 */

AtomicLongFieldUpdater

@since 1.5
/**
 * A reflection-based utility that enables atomic updates to
 * designated {@code volatile long} fields of designated classes.
 * This class is designed for use in atomic data structures in which
 * several fields of the same node are independently subject to atomic
 * updates.
 *
 * <p>Note that the guarantees of the {@code compareAndSet}
 * method in this class are weaker than in other atomic classes.
 * Because this class cannot ensure that all uses of the field
 * are appropriate for purposes of atomic access, it can
 * guarantee atomicity only with respect to other invocations of
 * {@code compareAndSet} and {@code set} on the same updater.
 *
 * @since 1.5
 * @author Doug Lea
 * @param <T> The type of the object holding the updatable field
 */

AtomicReferenceFieldUpdater

@since 1.5
/**
 * A reflection-based utility that enables atomic updates to
 * designated {@code volatile} reference fields of designated
 * classes.  This class is designed for use in atomic data structures
 * in which several reference fields of the same node are
 * independently subject to atomic updates. For example, a tree node
 * might be declared as
 *
 * <pre> {@code
 * class Node {
 *   private volatile Node left, right;
 *
 *   private static final AtomicReferenceFieldUpdater<Node, Node> leftUpdater =
 *     AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
 *   private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater =
 *     AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
 *
 *   Node getLeft() { return left; }
 *   boolean compareAndSetLeft(Node expect, Node update) {
 *     return leftUpdater.compareAndSet(this, expect, update);
 *   }
 *   // ... and so on
 * }}</pre>
 *
 * <p>Note that the guarantees of the {@code compareAndSet}
 * method in this class are weaker than in other atomic classes.
 * Because this class cannot ensure that all uses of the field
 * are appropriate for purposes of atomic access, it can
 * guarantee atomicity only with respect to other invocations of
 * {@code compareAndSet} and {@code set} on the same updater.
 *
 * @since 1.5
 * @author Doug Lea
 * @param <T> The type of the object holding the updatable field
 * @param <V> The type of the field
 */

Striped64

1.8加入的
/**
 * A package-local class holding common representation and mechanics
 * for classes supporting dynamic striping on 64bit values. The class
 * extends Number so that concrete subclasses must publicly do so.
 */

總結

JDK1.5中:

原子性更新基本型別:
AtomicBoolean:原子更新布林型別。
AtomicInteger:原子更新整型。
AtomicLong:原子更新長整型。

原子更新基本型別陣列:

AtomicIntegerArray:原子更新整型數組裡的元素。
AtomicLongArray:原子更新長整型數組裡的元素。

更新欄位:

抽象類:AtomicIntegerFieldUpdater: 原子更新整型欄位的更新器。
抽象類:AtomicLongFieldUpdater: 原子更新長整型欄位的更新器。
抽象類:AtomicReferenceFieldUpdater:原子更新引用型別裡的欄位。

更新引用型別:

AtomicReference:原子更新引用型別。

AtomicMarkableReference 原子更新帶有標記位的引用型別

AtomicStampedReference:原子更新帶有版本號的引用型別。該類將整數值與引用關聯起來,可用於原子的更資料和資料的版本號,可以解決使用CAS進行原子更新時,可能出現的ABA問題。

更新引用型別陣列:
AtomicReferenceArray:原子更新引用型別數組裡的元素。

JDK1.8中:

Striped64
JDK 8 的 java.util.concurrent.atomic 下有一個包本地的類 Striped64 ,它持有常見表示和機制用於類支援動態 striping 到 64bit 值上。

strping:
資料 striping 就是把邏輯上連續的資料分為多個段,使這一序列的段儲存在不同的物理裝置上。通過把段分散到多個裝置上可以增加訪問併發性,從而提升總體的吞吐量。

累加器:

DoubleAccumulator

DoubleAdder

LongAccumulator

LongAdder

1.8中的Double和Long累加器 將原本的

如Integer中

  do {
            prev = get();
            next = accumulatorFunction.applyAsInt(prev, x);
        } while (!compareAndSet(prev, next));

do while體系 變為

    public void add(long x) {
        Cell[] as; long b, v; int m; Cell a;
        if ((as = cells) != null || !casBase(b = base, b + x)) {
            boolean uncontended = true;
            if (as == null || (m = as.length - 1) < 0 ||
                (a = as[getProbe() & m]) == null ||
                !(uncontended = a.cas(v = a.value, v + x)))
                longAccumulate(x, null, uncontended);
        }
    }

1.
在標量 如 boolean,integer,long,reference.
其底層是CAS (compare and swap) + volatile和native方法,從而避免了synchronized的高開銷,執行效率大為提升

2.
AtomicIntegerArray,AtomicLongArray還有AtomicReferenceArray類進一步擴充套件了原子操作,對這些型別的陣列提供了支援。這些類在為其陣列元素提供 volatile 訪問語義方面也引人注目,這對於普通陣列來說是不受支援的。

他們內部並不是像AtomicInteger一樣維持一個valatile變數,而是全部由native方法實現,如下
AtomicIntegerArray的實現片斷

3.
AtomicLongFieldUpdater,AtomicIntegerFieldUpdater,AtomicReferenceFieldUpdater基於反射的實用工具,可以對指定類的指定 volatile 欄位進行原子更新。API非常簡單,但是也是有一些約束:

(1)欄位必須是volatile型別的

(2)欄位的描述型別(修飾符public/protected/default/private)是與呼叫者與操作物件欄位的關係一致。也就是說 呼叫者能夠直接操作物件欄位,那麼就可以反射進行原子操作。但是對於父類的欄位,子類是不能直接操作的,儘管子類可以訪問父類的欄位。

(3)只能是例項變數,不能是類變數,也就是說不能加static關鍵字。

(4)只能是可修改變數,不能使final變數,因為final的語義就是不可修改。實際上final的語義和volatile是有衝突的,這兩個關鍵字不能同時存在。

(5)對於AtomicIntegerFieldUpdater 和AtomicLongFieldUpdater 只能修改int/long型別的欄位,不能修改其包裝型別(Integer/Long)。如果要修改包裝型別就需要使用AtomicReferenceFieldUpdater 。

netty5.0中類ChannelOutboundBuffer統計傳送的位元組總數,由於使用volatile變數已經不能滿足,所以使用AtomicIntegerFieldUpdater 來實現的,看下面程式碼: