SORU
17 Mart 2012, CUMARTESİ


Atom / farkı / senkronize Değişken nedir?

Bazı çocuklar tekrarlanan bir soru olarak ele alacağız biliyorum... :) ama sadece benim açımdan nasıl Atom / DAHİLİ olarak çalışır mı ??

Aşağıdaki kod blokları arasında ne fark var....

:1 kod

private int counter;

public int getNextUniqueIndex() {
    return counter  ; 
}

:2 kod

private AtomicInteger counter;

public int getNextUniqueIndex() {
    return counter.getAndIncrement();
}

:3 kod

private Volatile int counter;

public int getNextUniqueIndex() {
    return counter  ; 
}

aşağıdaki şekilde Uçucu çalışıyor mu ??

volatile int i = 0;
void incIBy5() {
    i  = 5;
}

eşittir

void incIBy5() {
    int temp;
    synchronized(i) { temp = i }
    synchronized(i) { i = temp   5 }
}

İki iş parçacığı aynı anda Senkronize blok girebilirsiniz.. bilmiyorum haksız mıyım ?? bu Nasıl bu atom daha doğrudur.Senkronize ??) incrementAndGet çalışır ve iş parçacığı güvenli mi ??

Uçucu ve Değişken iç okuma ve yazma / Atom Değişken arasındaki fark nedir ?? bazı makalede değişkenler iş parçacığının yerel kopyasını bu nedir ?? okudum

Sorumu okuduğunuz için teşekkürler. Hardik

CEVAP
17 Mart 2012, CUMARTESİ


Özellikle ne hakkında soruyorsunDAHİLİ olarak çalışırbu yüzden burada:,

Eşitleme

private int counter;

public int getNextUniqueIndex() {
  return counter  ; 
}

Temelde hafıza, artışlarla bu değeri okur ve hafızasına geri koyar. Bu tek iş parçacığı çalışır ama günümüzde çok çekirdekli çağında, multi-CPU, çok seviyeli önbelleğe düzgün çalışmayacaktır. Öncelikle yarış durumu (çeşitli konuları aynı zamanda değerini okuyabilir), ama aynı zamanda görünürlük sorunları getirir. Değeri yalnızca saklı olabilir "yerel"Bellek (bazı önbellek) CPU ve diğer İşlemci/çekirdek için görünür (ve böylece - konuları) olacak. Bu çok bakın nedeni buduryerel kopyabir iş parçacığı bir değişken. Çok güvensiz. Düşünün popüler ama iş parçacığı kırık durdurma kodu:

private boolean stopped;

public void run() {
    while(!stopped) {
        //do some work
    }
}

public void pleaseStop() {
    stopped = true;
}

Ekle volatile stopped değişken ve gayet iyi çalışıyor - eğer başka bir iş parçacığı değiştirir stopped değişken) pleaseStop() yöntem, garantili için değişiklik anında çalışan iş parçacığı while(!stopped) döngü. Bu bir iş parçacığı ya da kesmek için iyi bir yol, görmek değildir BTW: How to stop a thread that is running forever without any use ve Stopping a specific java thread.

AtomicInteger

private AtomicInteger counter = new AtomicInteger();

public int getNextUniqueIndex() {
  return counter.getAndIncrement();
}

AtomicInteger sınıf kullanır CAS (compare-and-swap) düşük seviyeli CPU işlemleri (eşitleme gerekli!) Eğer bugünkü değeri başka bir şeye eşit (ve geri başarılı) ise sadece belirli bir değişkeni değiştirmek için izin verir. Yani getAndIncrement() çalıştırdığınızda aslında bir döngü (gerçek uygulama basitleştirilmiş) çalışır:

int current;
do {
  current = get();
} while(!compareAndSet(current, current   1));

Yani temelde bu: okumak; artan değeri saklamak için deneyin; değilse başarılı (değer artık current eşit) ve tekrar okumak deneyin. compareAndSet() yerel kod (Kurul) uygulanır.

volatile senkronizasyon olmadan

private volatile int counter;

public int getNextUniqueIndex() {
  return counter  ; 
}

Bu kod doğru değil. Görüş sorunu (volatile diğer iş değiştirmek counter yapılan görebilir emin olur) giderir ama hala bir yarış durumu vardır. Bu birden çok kez açıklandı: post-incrementation atom değil ön/.

volatile tek yan etkisidir "kızarma" diğer bütün partiler verilerin en taze sürümü görmek için önbelleğe alır. Bu çoğu durumda çok sıkı; volatile varsayılan değildir.

Senkronizasyon (2) volatile

volatile int i = 0;
void incIBy5() {
  i  = 5;
}

Aynı sorun yukarıdaki gibi, ancak i private olmadığı için daha da kötüsü. Yarış durumu hala mevcut. Neden sorun oluyor? Diyelim, iki iş parçacığı bu kodu aynı anda çalıştırırsanız, çıkış 5 10 - ama en azından değiştirme garantilidir olabilir.

Birden fazla bağımsız synchronized

void incIBy5() {
  int temp;
  synchronized(i) { temp = i }
  synchronized(i) { i = temp   5 }
}

Sürpriz, bu kod yanlış. Aslında tamamen yanlıştır. Öncelikle eşitleme i olduğu için değiştirilmesi (ayrıca i ilkel, sanırım eşitleme bir geçici Integer oluşturulan üzerinden autoboxing...) Tamamen hatalı. De yazabilirsiniz:

synchronized(new Object()) {
  //thread-safe, SRSLy?
}

Hiçbir iki iş parçacığı synchronized aynı blok girebilirsinizaynı kilit. Bu durumda (ve kodunuzda aynı şekilde) her kilit gerçekleşmesi halinde değişiklikler nesne, yani synchronized etkili hiçbir etkisi olmaz.

Eğer son değişken (veya this) eşitleme için kullanılan varsa bile, kod, hala yanlış. İki iş parçacığı ilk okuma i temp eşzamanlı (aynı değeri yerel olarak temp), sonra ilk atar yeni bir değer için i (1-6) ve diğeri de aynı şeyi yapıyor (1-6).

Eşitleme span gibi bir değer atamak için okumak gerekir. İlk eşitleme etkisi (int atomik bir okuma) ve ikincisi de vardır. Bu, Eğer bana sorarsan doğru formları vardır:

void synchronized incIBy5() {
  i  = 5 
}

void incIBy5() {
  synchronized(this) {
    i  = 5 
  }
}

void incIBy5() {
  synchronized(this) {
    int temp = i;
    i = temp   5;
  }
}

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Blendtec

    Blendtec

    30 EKİM 2006
  • eisleyhead

    eisleyhead

    11 Ocak 2006
  • knopik96

    knopik96

    7 Mayıs 2011