2009-07-15 7 views
20

Dizilerin bir dizinden bir iş parçacığı okumasıyla eşzamanlılık sorunları var mı, diğer bir iş parçacığı dizinin farklı bir dizinine yazıyor, dizinler farklı olduğu sürece?java dizisi iş parçacığı güvenliği

örn.

class Test1 
{ 
    static final private int N = 4096; 
    final private int[] x = new int[N]; 
    final private AtomicInteger nwritten = new AtomicInteger(0); 
    // invariant: 
    // all values x[i] where 0 <= i < nwritten.get() are immutable 

    // read() is not synchronized since we want it to be fast 
    int read(int index) { 
     if (index >= nwritten.get()) 
      throw new IllegalArgumentException(); 
     return x[index]; 
    } 
    // write() is synchronized to handle multiple writers 
    // (using compare-and-set techniques to avoid blocking algorithms 
    // is nontrivial) 
    synchronized void write(int x_i) { 
     int index = nwriting.get(); 
     if (index >= N) 
      throw SomeExceptionThatIndicatesArrayIsFull(); 
     x[index] = x_i; 
     // from this point forward, x[index] is fixed in stone 
     nwriting.set(index+1); 
    }  
} 

düzenlemek (bu örnek mutlaka sadece benim noktası göstermek için, gerçek kullanım için önerilmez): Bu örneği Eleştirilmesinin benim soru değil, ben gerçekten sadece eşzamanlı için, bir endekse eğer dizi erişimi bilmek istiyorum Başka bir dizinin erişimi, eşzamanlılık sorunları ortaya çıkarır, basit bir örnek düşünemedim.

cevap

12

diziler değiştirerek geçersiz bir eyalet almazsınız iken Bahsettiğiniz gibi, iki iş parçacığı senkronizasyon olmadan kalıcı olmayan bir tamsayı görüntülediğinde aynı sorunla karşılaşacaksınız (Memory Consistency Errors'da Java Eğitimi bölümündeki bölüme bakın). Temel olarak sorun, iş parçacığı 1, boşluk i'de bir değer yazabilir, ancak iş parçacığı 2 (veya) iş parçacığı değişikliği görecek olduğunda hiçbir garanti yoktur.

java.util.concurrent.atomic.AtomicIntegerArray sınıfı, yapmak istediğiniz şeyi yapar.

+0

teşekkürler ... drat, bayt [] dizisini kullanmak istedim ve Atom atomu yok gibi görünüyor .... Sanırım senkronize yöntemleri kullanacağım ve basit tutacağım. –

+2

Yazmaktan çok daha fazla okumanız varsa, java.util.concurrent.locks.ReadWriteLock –

+0

huh'ya bakmak isteyebilirsiniz, sadece anladığımdan emin olmak için: –

4

Örnekte, düzyazı sorusundan farklı birçok şey vardır.

Bu sorunun cevabı, bir dizinin farklı öğelerine bağımsız olarak erişilmesidir, bu nedenle, iki iş parçacığı farklı öğeleri değiştirirse eşitlemeye ihtiyacınız yoktur. Ancak, Java bellek modeli, erişimi senkronize etmedikçe, bir iş parçacığı tarafından yazılan bir değerin başka bir iş parçacığı tarafından görülebileceğine dair bir garanti vermez.

Gerçekte neyi başarmaya çalıştığınıza bağlı olarak, java.util.concurrent zaten sizin için yapacak bir sınıfa sahip olabilir. Ve eğer yapmazsa, kodunuzun hash tablosunu yönetmek için yaptıklarının aynısını yaptığı göründüğü için hala ConcurrentHashMap için kaynak koduna bakmanızı öneririz.

1

Yalnızca write yöntemini senkronize ederken, read yöntemini senkronize edilmeden bırakılırken gerçekten işe yaramayacağından emin değilim. Aslında tüm sonuçları değil, en azından write tarafından geçersiz kılınan bazı değerleri döndüren read yöntemine yol açabilir.

1

Evet, hatalı önbellek araya getirme işlemi birden çok CPU/çekirdek ortamında gerçekleşebilir. Bunu önlemek için çeşitli seçenekler vardır:

  • Kullanım atomik bir dizideki öğeye set (veya jsr166y eklenen özellik
  • Kullanım AtomicXYZ [] dizi
  • Kullanım özel Java7 içinde için güvenli olmayan Sun-özel kütüphane bir uçucu alanıyla nesne ve bu nesnenin bir dizi var.
  • Kullanım jsr166y zeyilname ParallelArray yerine algoritmada
1

okuma() senkronize olmadığından şu scen olabilir ario:

Thread A enters write() method 
Thread A writes to nwriting = 0; 
Thread B reads from nwriting =0; 
Thread A increments nwriting. nwriting=1 
Thread A exits write(); 

bir uçuş kartı beri bu senin değişken adresleri asla çatışma ne (dizi indeksi sorunlarını indirim) böyle bir şey:

int i; 
synchronized int curr(){ return i; } 
synchronized int next(){ return ++i;} 

int read() { 
     return values[curr()]; 
    } 

void write(int x){ 
    values[next()]=x; 
} 
+0

teşekkürler, ama sorum ve senaryomuz gerçekleşemez (2 ve 3. adımlar asla oluşmaz) –