2013-04-03 17 views
7

zaten koleksiyon synchronzied edilir ve böylelikle güvenli iş parçacığı oluyor. Fakat yineleme için neden tekrar synchronized(c)'u kullanmalıyız? Gerçekten kafam karıştı. Teşekkürler.Senkronize toplama c yana

"üzerinde yineleme kullanıcı el döndü koleksiyonu senkronize zorunludur: bu tavsiyeye uymak

Collection c = Collections.synchronizedCollection(myCollection); 
... 
synchronized(c) { 
    Iterator i = c.iterator(); // Must be in the synchronized block 
    while (i.hasNext()) { 
     foo(i.next()); 
    } 
} 

Arıza belirli olmayan davranışlara neden olabilir." http://docs.oracle.com/javase/6/docs/api/java/util/Collections.

cevap

10

Tüm synchronized koleksiyonlarının gerçekleştirilmesi, muhtemelen her bireysel yönteminin numaralı telefonunun senkronize olduğunu garanti etmektir. Ancak yineleme zorunlu olarak birden fazla ayrı yöntem çağrısını içerir, böylece senkronize edilmiş koleksiyonun kullanıcısı, tüm yineleme üzerinde kendiniz senkronize etmeniz gerekir. Eğer c üzerinde senkronize olmasaydı

Örneğin, koleksiyon içeriği i.hasNext() ve i.next() arasında değişebilir - hatta i.next() başarısız olur ki bu durumda artık unsurları, sahip olmanın unsurları sahip olmaktan gidebiliriz.

+0

siz "ille birden fazla ayrı yöntem çağrıları içeren" ile ne demek istiyorsunuz? – user697911

+1

user697911 @: 'i.hasNext()' ve 'i.next()' iki ayrı yöntem çağrıları vardır ve hiçbir şekilde hiçbir şeyin i.hasNext 'arasındaki değişiklikleri sağlamak için Collections.synchronizedCollection'' uygulanması için var() 've' i.next() '. –

+0

Yani, eşzamanlıHashmap aynı olurdu? Eşzamanlılığı eşzamanlı olarak senkronize etmek zorunda mıyız? – user697911

4

bireysel parçacığı güvenli olanlar yöntemlerin (bir grupta onları çağıran) bir toplama yapmaz senkronize bir sınıf üzerinde tüm yöntemleri yapma. Senkronize edilmiş bir bloğa Iterator'u sarmak suretiyle, yineleyicinin o özel örneğini, birden çok iş parçacığı tarafından diğer çağrılar ile serpiştirilmiş olarak adlandırılan bireysel yöntemini korumasını korursunuz.

Ben mantıklı bir ifade tamamlamak için .add() birden çok kez aramak gerekirse o, güvenli bir kez .add() çağırırsanız

, başkası benim .add() çağrılar arasında başka bir şey ya da başka kaldırıldı şey eklemedi hiçbir garantisi yoktur I sürece .add() (veya başka bir yöntem) koleksiyonunu temsil değişkeni synchronizing tarafından çağıran diğer her şeyi bloke ederler.

Iterator hepsi onları türlü tek transaction olarak yürütmek yapmak için tek synchronized blokta sarılmış lazım, koleksiyonunda bireysel yöntemlere mutiple çağrı yapar. Iterator implemenasyonunun kaynak kodunu inceleyin, ne demek istediğimi göreceksiniz. İşte, List için kaynak kodu, altta yatan uygulamaya çok sayıda bireysel çağrı yapar, böylece hepsi, aynı iş parçacığı tarafından kesintisiz olarak yürütülmesi için belirlenir.

@Override 
    public Iterator<A> iterator() { 
     if (tail == null) 
      return emptyIterator(); 
    return new Iterator<A>() { 
     List<A> elems = List.this; 
     public boolean hasNext() { 
     return elems.tail != null; 
     } 
     public A next() { 
       if (elems.tail == null) 
        throw new NoSuchElementException(); 
     A result = elems.head; 
     elems = elems.tail; 
     return result; 
     } 
     public void remove() { 
     throw new UnsupportedOperationException(); 
     } 
    }; 
    } 

AbstractList.iterator() için source birden fazla çağrı yapar daha da karmaşık mantığı gösterir.

Daha iyi bir sarıcı Immutable koleksiyonlarında onları tamamlıyor, o zaman başka bir şey çağrılar arasında yatan koleksiyon değiştirebilir garanti.

+1

en iyi açıklama Ben rastladım! – kellogs