Uczynienie wszystkich metod na indywidualnie zsynchronizowanej klasie nie powoduje agregacji (wywoływania ich w grupie) tych metod. Przez zawijanie Iterator
w zsynchronizowanym bloku chronisz to konkretne wystąpienie iteratora przed tym, czy jego pojedyncza metoda jest nazywana przeplatana z innymi wywołaniami przez wiele wątków.
Jeśli zadzwonię .add()
raz to jest bezpieczne, jeśli trzeba zadzwonić .add()
wiele razy, aby zakończyć logiczne stwierdzenie, nie ma gwarancji, że ktoś inny nie dodała coś innego lub usunięty coś innego między moimi .add()
połączeń, chyba że zablokuj wszystko inne, wywołując .add()
(lub inną metodę) przez synchronizing
dla zmiennej reprezentującej kolekcję.
Iterator
sprawia mutiple połączeń do poszczególnych metod w kolekcji, wszystkie one muszą być opakowane w jednym synchronized
bloku aby je wykonać jako pojedynczy transaction
rodzajów. Zbadaj kod źródłowy implementacji Iterator
, zobaczysz co mam na myśli. Oto kod źródłowy dla List
wykonuje wiele indywidualnych wywołań do podstawowej implementacji, więc wszystkie muszą być wykonane w nieprzerwanej kolejności przez ten sam wątek, aby były deterministyczne.
@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();
}
};
}
source dla AbstractList.iterator()
pokazuje jeszcze bardziej skomplikowana logika sprawia, że wiele połączeń.
Lepszym opakowaniem jest zawijanie ich w kolekcjach Immutable
, a następnie gwarantuje się, że nic innego nie może zmienić podstawowej kolekcji między połączeniami.
Co rozumiesz przez "koniecznie obejmuje wiele oddzielnych wywołań metod"? – user697911
@ user697911: 'i.hasNext()' i 'i.next()' są dwoma oddzielnymi wywołaniami metod i nie ma możliwości zastosowania 'Collections.synchronizedCollection' w celu zapewnienia, że nic nie zmieni się pomiędzy' i.hasNext() 'i' i.next() '. –
Tak więc, współbieżnaHashmapa byłaby taka sama? Czy musimy również synchronizować concurrenthashamp w iteracji? – user697911