Java並發包:AtomicBoolean和AtomicReference
AtomicBoolean
AtomicBoolean是一個讀和寫都是原子性的boolean類型的變量。這裏包含高級的原子操作,例如compareAndSet()。AtomicBoolean位於Java.util.concurrent.atomic包中,因此全類名是java.util.concurrent.atomic.AtomicBoolean。這篇文章講述的AtomicBoolean的版本可以在java 8中找到,第一個版本在java 5中增加。
AtomicBoolean設計背後的原理在我的另一篇文章Compare and Swap有解釋。
創建AtomicBoolean
你可以像下面一樣創建一個AtomicBoolean:
AtomicBoolean atomicBoolean = new AtomicBoolean();
- 1
這個例子創建了一個AtomicBoolean默認值為false。
如果你需要顯示的設置AtomicBoolean的初始值,你可以給AtomicBoolean傳遞一個初始值。
AtomicBoolean atomicBoolean = new AtomicBoolean(true);
- 1
- 獲取AtomicBoolean的值
你可以使用get()方法獲取AtomicBoolean的值,下面是一個例子:
AtomicBoolean atomicBoolean = new AtomicBoolean(true);
boolean value = atomicBoolean.get();
- 1
- 2
- 3
執行上面的代碼後value變量的值將為ture。
- 設置AtomicBoolean的值
你可以使用set()方法設置AtomicBoolean的值,下面是一個例子:
AtomicBoolean atomicBoolean = new AtomicBoolean(true);
atomicBoolean.set(false);
- 1
- 2
- 3
執行上面的代碼後atomicBoolean 變量的值將為false。
- 交換AtomicBoolean的值。
你可以使用getAndSet()交換AtomicBoolean的值。getAndSet()方法返回AtomicBoolean當前的值,並給它設置一個新的值。下面是一個例子:
AtomicBoolean atomicBoolean = new AtomicBoolean(true);
boolean oldValue = atomicBoolean.getAndSet(false);
- 1
- 2
- 3
執行上面的代碼後oldValue的值為true,AtomicBoolean實例的值為false.代碼有效的交換了當前值為true的AtomicBoolean值使之為false。
- 比較和設置AtomicBoolean的值
compareAndSet()可以使AtomicBoolean的當前值和你期望的值作對比。如果當前值就是你期望的值,一個新的值會在AtomicBoolean上設置。compareAndSet()方法是原子的,因此,同一時刻僅允許一個線程執行它。於是,compareAndSet()方法可以用於實現簡單的同步器例如鎖。
下面是使用compareAndSet()的例子:
AtomicBoolean atomicBoolean = new AtomicBoolean(true);
boolean expectedValue = true;
boolean newValue = false;
boolean wasNewValueSet = atomicBoolean.compareAndSet(
expectedValue, newValue);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
這個例子中把AtomicBoolean的當前值和true做對比,如果兩個值相等,將會給AtomicBoolean設置一個新值false。
AtomicReference
AtomicReference類提供了一種讀和寫都是原子性的對象引用變量。原子意味著多個線程試圖改變同一個AtomicReference(例如比較和交換操作)將不會使得AtomicReference處於不一致的狀態。AtomicReferenc的compareAndSet()方法可以使得它與期望的一個值進行比較,如果他們是相等的,AtomicReference裏的對象會被設置成一個新的引用。
創建AtomicReference
你可以下面這樣創建一個AtomicReference的實例。
AtomicReference atomicReference = new AtomicReference();
- 1
如果你需要使用一個初始引用來創建AtomicReference,你可以像下面這樣做。
String initialReference = "the initially referenced string";
AtomicReference atomicReference = new AtomicReference(initialReference);
- 1
- 2
- 創建泛型AtomicReference
你可以使用java泛型創建一個類型化的AtomicReference。下面是一個例子:
AtomicReference<String> atomicStringReference =
new AtomicReference<String>();
- 1
- 2
你也可以給類型化的AtomicReference指定初始值,下面是給類型化的AtomicReference指定初始值的例子:
String initialReference = "the initially referenced string";
AtomicReference<String> atomicStringReference =
new AtomicReference<String>(initialReference);
- 1
- 2
- 3
獲得AtomicReference引用
你可以使用AtomicReference的get()方法獲的存儲在AtomicReference中的引用。如果你在非泛型化的AtomicReference上使用get()方法將會返回一個Object引用。如果在泛型化的AtomicReference上使用get()方法將會返回你在AtomicReference上聲明的類型的引用。
下面是一個非泛型化的AtomicReference的get()的例子:
AtomicReference atomicReference = new AtomicReference("first value referenced");
String reference = (String) atomicReference.get();
- 1
- 2
- 3
註意,當AtomicReference是一個非泛型化的時,必須將get()方法返回的引用強制轉換為String,因為get()放好的是一個Object引用。
下面是一個泛型化的AtomicReference的例子:
AtomicReference<String> atomicReference =
new AtomicReference<String>("first value referenced");
String reference = atomicReference.get();
- 1
- 2
- 3
- 4
註意,這裏不需要將get()返回的引用進行強制轉換,因為編譯器知道它返回一個String引用。
設置AtomicReference引用
你可以使用set()方法設置儲存在AtomicReferenc實例中的引用。對於非泛型化的AtomicReference的實例,set()方法會將一個Object引用作為參數。對於泛型化的AtomicReference,set()方法將使用你在AtmoicReference上聲明的類型的引用作為參數。
下面是一個AtomicReference的set()的例子:
AtomicReference atomicReference =
new AtomicReference();
atomicReference.set("New object referenced");
- 1
- 2
- 3
- 4
對於泛型和非泛型的引用在使用set()上看起並沒有什麽不同。唯一的不同是編譯器會對泛型的AtomicReference有類型約束。
比較和設置AtomicReference引用
AtomicReference有一個非常有用的方法是compareAndSet()。compareAndSet()方法可以將存儲在AtomicReference中的引用同你的預期值做一個比較,如果他們是相同的(not equal as in equals() but same as in ==),那麽在AtomicReference實例上會設置一個新的引用。
如果compareAndSet()方法給AtomicReference設置了新的引用,它會返回true。否則會返回false。
下面是AtomicReference compareAndSet()方法的例子:
String initialReference = "initial value referenced";
AtomicReference<String> atomicStringReference =
new AtomicReference<String>(initialReference);
String newReference = "new value referenced";
boolean exchanged = atomicStringReference.compareAndSet(initialReference, newReference);
System.out.println("exchanged: " + exchanged);
exchanged = atomicStringReference.compareAndSet(initialReference, newReference);
System.out.println("exchanged: " + exchanged);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
上面的例子中使用了一個初始的引用創建了一個泛型化的AtomicReference。然後調用兩次compareAndSet()方法來比較儲存的引用和初始的引用。如果儲存的引用與初始引用是相等的將會設置一個新的引用。第一次的時候兩個引用是相等的,因此AtomicReference被設置了一個新的引用。第二次儲存的引用是之前調用compareAndSet()放新設置的引用,因此儲存的引用一定是與初始的引用是不相等的。於是,AtomicReference不會被設置成一個新的引用,compareAndSet()方法返回false。
Java並發包:AtomicBoolean和AtomicReference