Yanıtlar:
Birden fazla iş parçacığının boole değerini kontrol etmesi ve değiştirmesi gerektiğinde. Örneğin:
if (!initialized) {
initialize();
initialized = true;
}
Bu iş parçacığı için güvenli değildir. Şunları kullanarak düzeltebilirsiniz AtomicBoolean
:
if (atomicInitialized.compareAndSet(false, true)) {
initialize();
}
true
zaman initialize()
tamamlanmış değil. Bu nedenle, yalnızca diğer iş parçacıklarının tamamlanması umurumda değilse çalışır initialize()
.
initialized
Sadece tek bir iş parçacığının initialize()
yöntemi çağıracağından emin olmak için kullanılıyorsa, bunun geçerli bir gerçek dünya örneği olduğunu düşünüyorum . Açıkçası initialized
doğru olmak, bu durumda başlatmanın kesinlikle tamamlandığı anlamına gelmez, bu yüzden belki biraz farklı bir terim burada daha iyi olurdu. Yine, ne için kullanıldığına bağlıdır.
volatile boolean
aynı olmaz mıydı AtomicBoolean
?
synchronized
blok kullanmaktır , bu durumda artık bir a'ya ihtiyacınız yoktur AtomicBoolean
, sadece a volatile boolean
. ( if(! this.initialized) { synchronized(this) { if(! this.initialized) { initialize(); this.initialized = true; } } }
yalnızca bir iş parçacığının çağrılmasını initialize
ve diğer tüm iş parçacıklarının initialized
işaretlenmesi koşuluyla bunu yapmasını beklemesini sağlar volatile
.)
İşte yaptığım notlar ( Brian Goetz kitabından ), bu size yardımcı olabilir
AtomicXXX sınıfları
Engellemeyen Karşılaştır ve Takas uygulamasını sağlayın
Donanım tarafından sağlanan desteğin avantajlarından yararlanır (Intel'deki CMPXCHG talimatı) Kodunuzda bu atomik eşzamanlılık API'sını kullanan çok sayıda iş parçacığı çalıştırıldığında, Nesne düzeyi monitörleri / senkronizasyonu kullanan koddan çok daha iyi ölçeklenirler. Java'nın senkronizasyon mekanizmaları kodu beklettiğinden, kritik bölümlerinizden geçen çok sayıda iş parçacığı olduğunda, senkronizasyon mekanizmasının kendisini yönetmek için önemli miktarda CPU zamanı harcanır (bekleme, bildirim vb.). Yeni API, donanım düzeyinde yapılar (atomik değişkenler) kullandığından ve iş parçacığı güvenliğini uygulamak için serbest algoritmaları bekleyip kilitlediğinden, senkronizasyonu yönetmek yerine çok daha fazla CPU zamanı harcar.
sadece daha iyi verim sunmakla kalmaz, aynı zamanda kilitlenme ve öncelikli ters çevirme gibi canlılık sorunlarına daha fazla direnç sağlar.
Atomik bir boole kullanmanızın iki ana nedeni vardır. İlk olarak değiştirilebilir, örneğin bir referans olarak iletebilir ve örneğin boole ile ilişkili olan değeri değiştirebilirsiniz.
public final class MyThreadSafeClass{
private AtomicBoolean myBoolean = new AtomicBoolean(false);
private SomeThreadSafeObject someObject = new SomeThreadSafeObject();
public boolean doSomething(){
someObject.doSomeWork(myBoolean);
return myBoolean.get(); //will return true
}
}
ve someObject sınıfında
public final class SomeThreadSafeObject{
public void doSomeWork(AtomicBoolean b){
b.set(true);
}
}
Daha da önemlisi, iş parçacığı güvenlidir ve sınıfı koruyan geliştiricilere, bu değişkenin değiştirilmesinin ve birden çok iş parçacığından okunmasının beklendiğini gösterebilir. AtomicBoolean kullanmıyorsanız, kullandığınız boolean değişkenini geçici olarak bildirerek veya alanın okuma ve yazma çevresinde senkronize ederek senkronize etmeniz gerekir.
AtomicBoolean
Sınıf size atomik güncelleyebildiğinizi bir boole değeri verir. Bir boole değişkenine erişen birden çok iş parçacığınız varsa bunu kullanın.
Java.util.concurrent.atomic paket bakış bu pakette sınıfları yapmak ve bunları kullanmak için ne iyi bir üst düzey açıklamasını verir. Ayrıca Brian Goetz'un Pratikte Java Concurrency kitabını da öneririm .
Paket açıklamasından alıntı
Paket java.util.concurrent.atomic açıklama: Tek değişkenler üzerinde kilitsiz iş parçacığı güvenli programlamayı destekleyen sınıfların küçük bir araç seti. [...]
Bu yöntemlerin özellikleri, uygulamaların çağdaş işlemcilerde kullanılabilen verimli makine düzeyinde atomik talimatlar kullanmasını sağlar. [...]
AtomicBoolean, AtomicInteger, AtomicLong ve AtomicReference sınıflarının örnekleri, karşılık gelen türde tek bir değişkene erişim ve güncellemeler sağlar. [...]
Atomiklerin erişimleri ve güncellemeleri için bellek etkileri genellikle uçucular için olan kurallara uyar:
- get, değişken bir değişkenin okunmasının hafıza etkilerine sahiptir.
- set, değişken bir değişken yazma (atama) gibi bellek etkilerine sahiptir.
- poorCompareAndSet, bir değişkeni atomik olarak okur ve koşullu olarak yazar, bu değişken üzerindeki diğer bellek işlemlerine göre sıralanır, ancak normalde kalıcı bir bellek işlemi olarak işlev görür.
- CompareAndSet ve getAndIncrement gibi diğer tüm okuma ve güncelleme işlemleri, değişken değişkenlerin hem okunması hem de yazılmasının bellek etkilerine sahiptir.
volatile boolean
vsAtomicBoolean
: stackoverflow.com/questions/3786825/…