Java'da AtomicBoolean'ı ne zaman kullanmam gerekir?


Yanıtlar:


244

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();
}

51
Bu gerçek dünyadan bir örnek gibi görünmüyor - diğer iplik görebilirsiniz truezaman initialize()tamamlanmış değil. Bu nedenle, yalnızca diğer iş parçacıklarının tamamlanması umurumda değilse çalışır initialize().
axtavt

6
@axtavt: initializedSadece 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ı initializeddoğ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.
ColinD

14
initStarted ve initCompleted için 2 boole gerekir, sonra ilk iş parçacığı initStarted ayarlar ve initialise () öğesini çağırır, geri kalanı initCompleted doğru olana kadar bekleyin.
Martin

3
@Bozho - boolean alanlarına okur ve yazar atomik doğru mu ?, Şimdi, uçucu bana boolean alanının son değerini veriyor. Yani, etkili bir şekilde, volatile booleanaynı olmaz mıydı AtomicBoolean?
TheLostMind

2
@ Martin: Bir booleanın gerçekleşmesini beklemenin doğrudan bir yolu yoktur; ek mekanizmalara ihtiyacınız var. En mantıklı yaklaşım bir synchronizedblok 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ı initializeve diğer tüm iş parçacıklarının initializedişaretlenmesi koşuluyla bunu yapmasını beklemesini sağlar volatile.)
ruakh

52

İş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.


34

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.


4
Tanrı sevgisi için, bu sadece nesnenin kendisinin değişebilirliğini göstermekti. Özellikle gösteri amacıyla yazdım.
John Vint

Ve dahası, eğer bu TÜM olsaydı evet, o zaman her zaman doğru dönecektir
John Vint

Bu, iş parçacığı açısından güvenli olup olmadığını kanıtlamaz. Sınıfı çok güvenli hale getirmek için kod parçacıklarımı bitirebilirim, ancak bu sadece benim açımdan öldürür.
John Vint

1
Bence sadece Uçucu yeterli değil. Aynı değeri doğrudan ana bellekten okuyan ve yazan iki iş parçacığının, bu iş parçacıkları arasında herhangi bir eşitleme olmadığı bir durumu düşünün - eşzamanlı eşzamanlılık sorunları ortaya çıkabilir.
Shay Tsadok

1
OP'den bu varsayımı yapacak yeterli bağlam olmasa da, atomik set için yeterli olmayacaksınız, operasyonları kontrol edin. Söylemek gerekirse, elbette duruma bağlı olarak uçucu yeterli olmayabilir.
John Vint


5

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.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.