[英]Real life use and explanation of the AtomicLongFieldUpdate class
您可以考慮以下成本階梯:
long
:便宜,但對多線程訪問不安全volatile long
:更昂貴,多線程訪問安全,不可能進行原子操作AtomicLong
: 最昂貴的,對於多線程訪問安全,可以進行原子操作(當我說“不安全”或“不可能”時,我的意思是“沒有像同步這樣的外部機制”。)
在需要多線程訪問的情況下,但大多數操作都是簡單的讀或寫,只需要很少的原子操作,你可以創建一個AtomicLongFieldUpdate
靜態實例,並在需要原子更新時使用它。 內存/運行時開銷類似於一個簡單的volatile
變量,除了原子操作的數量級(或比普通AtomicLong
操作稍貴)。
這是一個不錯的小教程。
你會使用例如 AtomicLongFieldUpdater 而不是 AtomicLong 的原因只是為了減少堆成本。 在內部,兩者在 compareAndSet 級別上的工作方式幾乎相同,最后都使用 sun.misc.Unsafe。
假設您有一個初始化 1000k 次的類。 使用 AtomicLong,您將創建 1000k AtomicLongs。 另一方面,使用 AtomicLongFieldUpdater,您將創建 1 個 CONSTANT AtomicLongFieldUpdater 和 1000k 長的原語,這當然不需要太多的堆空間。
有人知道
AtomicLongFieldUpdate
類在現實生活中的用途嗎?
我自己從未使用過這個類,但在我的工作區中使用 get 時,我看到了幾個“現實生活”的使用實例:
com.google.common.util.concurrent.AtomicDouble
使用它來原子地修改其內部volatile long
字段,該字段使用Number.doubleToRawLongBits(...)
存儲來自double
的位。 很酷。
net.sf.ehcache.Element
使用它來自動更新hitCount
字段。
我已經閱讀了描述,但我還沒有完全理解它的含義。
它基本上提供與AtomicLong
相同的功能,但在另一個類的本地字段上。 AtomicLongFieldUpdate
的內存負載小於AtomicLong
,因為您為每個字段配置了一個更新實例,從而降低了內存開銷,但來自反射的 CPU 開銷更多(盡管可能很小)。
javadocs 說:
此類設計用於原子數據結構,其中同一節點的多個字段獨立地進行原子更新。
當然,但我只會使用多個Atomic*
字段。 我使用該類的唯一原因是,如果有一個我無法更改的現有類,我想以原子方式遞增。
當然。 最近在看阿里巴巴德魯伊。 我發現AtomicLongFieldUpdater
在這個項目中被廣泛使用。
// stats
private volatile long recycleErrorCount = 0L;
private volatile long connectErrorCount = 0L;
protected static final AtomicLongFieldUpdater<DruidDataSource> recycleErrorCountUpdater
= AtomicLongFieldUpdater.newUpdater(DruidDataSource.class, "recycleErrorCount");
protected static final AtomicLongFieldUpdater<DruidDataSource> connectErrorCountUpdater
= AtomicLongFieldUpdater.newUpdater(DruidDataSource.class, "connectErrorCount");
如上所述,屬性recycleErrorCount
和connectErrorCount
用於計算錯誤發生的次數。 相當多的DataSource
(持有上述屬性的類)將在應用程序生命周期內創建,在這種情況下,使用ALFU
比使用AtomicLong
明顯減少堆空間消耗。
原子通常用於並行編程。
在work-stealing模式下,只支持async、finish、forasync、isolated和atomic變量。
您可以將原子視為一種安全保護,可以避免數據競爭和並行編程中需要關注的其他問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.