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
Ö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;
}
}
MVP ve MVC nedir ve farkı nedir?...
'klasik arasındaki farkı' ve...
Yüce metin ve Github arasındaki fark&#...
Unut hg ve hg arasındaki farkı kaldırm...
Değişken ve işlev adları için Python a...