Neden bu Java programı görünüşte rağmen sonlandırmak gerekir't ('t etmedi.
Laboratuarda hassas bir operasyon, bugün tamamen ters gitti. Elektron mikroskobunda bir çalıştırıcı sınırının üzerine çıktı ve olaylar zinciri sonrasında ekipman 12 milyon dolar kaybettim. Bu hatalı modül üzerinde 40K satırları kısalttım:
import java.util.*;
class A {
static Point currentPos = new Point(1,2);
static class Point {
int x;
int y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public static void main(String[] args) {
new Thread() {
void f(Point p) {
synchronized(this) {}
if (p.x 1 != p.y) {
System.out.println(p.x " " p.y);
System.exit(1);
}
}
@Override
public void run() {
while (currentPos == null);
while (true)
f(currentPos);
}
}.start();
while (true)
currentPos = new Point(currentPos.x 1, currentPos.y 1);
}
}
Çıktı ben bazı örnekler alıyorum:
$ java A
145281 145282
$ java A
141373 141374
$ java A
49251 49252
$ java A
47007 47008
$ java A
47427 47428
$ java A
154800 154801
$ java A
34822 34823
$ java A
127271 127272
$ java A
63650 63651
Herhangi bir kayan nokta aritmetik burada yok, ve biz tüm tamsayılar iyi Java taşma uslu imzalı biliyorum bu yana, bu kod ile yanlış bir şey olduğunu düşünürdüm. Ancak, çıkış programdan çıkmak koşulu ulaşamadı, çıkış durumuna ulaştığını gösteren (hem de ulaşıldı . rağmen ^strong>veulaşmış değil mi?). Neden?
Bu bazı ortamlarda olmuyor fark ettim. 64-bit Linux üzerinde OpenJDK 6 yapıyorum.
CEVAP
Bu currentPos yazmak açıkçası bunu okumak oldu-önce değil, ama bu sorunu nasıl görmüyorum.
currentPos = new Point(currentPos.x 1, currentPos.y 1);
bazı şeyler x
y
(0) varsayılan değerlerini yazma ve yapıcı başlangıç değerlerine yazma da dahil olmak üzere. Nesne güvenli bir şekilde yayımlanmaz beri bu 4 yazma işlemlerinin serbestçe derleyici / JVM tarafından yeniden düzenlenebilir.
Okuma iplik açıdan baktığımızda, örneğin, 0 varsayılan değeri ile ama y
yeni değeri ile x
okumak için hukuki bir infaz. Zaman println
deyim bu arada eşitlenir ve bu nedenle okuma işlemleri etkisi yapar) ulaşmak, değişkenleri başlangıç değerlerine ve program beklendiği değerlerini yazdırır.
İşaretleme currentPos
volatile
güvenli yayını beri nesnedir etkili değişmez - eğer senin gerçek olarak, bir nesne mutasyona uğramış sonra inşaat, volatile
garanti olmayacak ve yeterli olabilir görmek tutarsız bir nesne daha.
Alternatif olarak, güvenli yayını sağlayacak Point
değişmez, hatta volatile
kullanmadan yapabilirsiniz. Değişmezliğini tanıdı elde etmek için, sadece x
y
final olarak işaretlemek gerekir.
Daha önce de belirttiğim gibi bir yan not olarak, synchronized(this) {}
JVM tarafından yok-op olarak tedavi edilebilir (ben bu davranışı yeniden oluşturmak için dahil anlamak).
Neden Ortamı yok.() Çıkış programı art...
Neden Java equals ve hashCode yöntemle...
Neden ThreadLocal değişkenler statik J...
Neden char[] şifreler için Dize Java t...
Neden belirli Unicode karakterler içer...