在本教程中,我們將講講 Java atomic 類(如 AtomicInteger
和 AtomicReference
)的方法 set()
和 lazySet()
之間的區(qū)別。
原子變量
Java中的原子變量使我們能夠輕松地對類的引用或字段進行線程安全的操作,而不需要添加監(jiān)視器或互斥等并發(fā)原語。
它們被定義在 java.util.concurrent.atomic
包下,雖然它們的API根據(jù)原子類型的不同而不同,但大多數(shù)都支持set()
和lazySet()
方法。
為了簡單起見,我們將在本文中使用 AtomicReference
和 AtomicInteger
,但同樣的原則適用于其他原子類型。
3.The set()
方法
在調(diào)用set()
后,當我們從不同的線程使用get()
方法訪問該字段時,該變化是立即可見的。這意味著該值被從CPU緩存中刷新到了所有CPU核共有的內(nèi)存層。為了展示上述功能,讓我們創(chuàng)建一個最小的 producer-consumer 控制臺應用。
public class Application {
AtomicInteger atomic = new AtomicInteger(0);
public static void main(String[] args) {
Application app = new Application();
new Thread(() - > {
for (int i = 0; i < 10; i++) {
app.atomic.set(i);
System.out.println("Set: " + i);
Thread.sleep(100);
}
}).start();
new Thread(() - > {
for (int i = 0; i < 10; i++) {
synchronized (app.atomic) {
int counter = app.atomic.get();
System.out.println("Get: " + counter);
}
Thread.sleep(100);
}
}).start();
}
}
在控制臺,我們應該看到一系列的 "設(shè)置 "和 "獲取 "信息。
Set: 3
Set: 4
Get: 4
Get: 5
表明緩存一致性的是,"Get "語句中的值總是等于或大于其上方的 "Set "語句中的值。。
這種行為雖然非常有用,但也帶來了性能上的影響。如果我們能在不需要緩存一致性的情況下避免它,那就太好了。
The lazySet()
方法
lazySet()
方法與set()
方法相同,但沒有緩存刷新。
換句話說,我們的變化最終只對其他線程可見。這意味著從不同的線程對更新的 AtomicReference
調(diào)用 get()
可能會給我們帶來舊的值。
為了看到這一點,讓我們在之前的控制臺應用程序中改變第一個線程的Runnable
。
for (int i = 0; i < 10; i++) {
app.atomic.lazySet(i);
System.out.println("Set: " + i);
Thread.sleep(100);
}
新的 "設(shè)置 "和 "獲取 "信息可能不總是遞增的。
Set: 4
Set: 5
Get: 4
Get: 5
由于線程的特性,我們可能需要重新運行幾次應用程序,以便觸發(fā)這種行為。盡管生產(chǎn)者線程已經(jīng)將AtomicInteger
設(shè)置為5,但消費者線程還是先檢索到了值4,這意味著當lazySet()
被使用時,系統(tǒng)最終是一致的。
在更多的技術(shù)術(shù)語中,我們說lazySet()
方法在代碼中不作為發(fā)生在前的邊,與它們的set()
對應的方法相反。
什么時候使用lazySet()
?
我們并不清楚什么時候應該使用lazySet()
,因為它與set()
的區(qū)別很微妙。我們需要仔細分析這個問題,不僅要確保我們會得到性能上的提升,還要確保在多線程環(huán)境下的正確性。
我們可以使用的一種方式是,一旦我們不再需要一個對象的引用,就用null
替換它。這樣,我們表明該對象有資格進行垃圾回收,而不會產(chǎn)生任何性能上的損失。我們假設(shè)其他線程可以使用廢棄的值,直到他們看到AtomicReference
是null
。不過一般來說,我們應該使用lazySet()
,當我們想對一個原子變量進行修改,而且我們知道這個修改不需要立即對其他線程可見。
總結(jié)
在這篇文章中,我們看了原子類的set()
和lazySet()
方法之間的區(qū)別。我們還學習了何時使用哪種方法。
-
內(nèi)存
+關(guān)注
關(guān)注
8文章
3004瀏覽量
73900 -
JAVA
+關(guān)注
關(guān)注
19文章
2960瀏覽量
104563 -
API
+關(guān)注
關(guān)注
2文章
1487瀏覽量
61831 -
SET
+關(guān)注
關(guān)注
0文章
17瀏覽量
7937 -
線程安全
+關(guān)注
關(guān)注
0文章
13瀏覽量
2456
發(fā)布評論請先 登錄
相關(guān)推薦
評論