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 來實現的,看下面程式碼: