SORU
23 NİSAN 2013, Salı


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
1 Mayıs 2013, ÇARŞAMBA


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).

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • ghosti66

    ghosti66

    27 AĞUSTOS 2006
  • HSmasteryoda .

    HSmasteryoda

    22 Ocak 2010
  • newreleaseblitz

    newreleasebl

    13 Ocak 2010