2016-01-04 12 views
5

ho deciso di scavare nel codice sorgente un po 'e ho notato che Collections.synchronizedList(List) viene implementato come segue:È sicuro iterare su wrapper sincronizzati?

public static <T> List<T> synchronizedList(List<T> list) { 
    return (list instanceof RandomAccess ? 
     new SynchronizedRandomAccessList<T>(list) : 
     new SynchronizedList<T>(list)); 
} 

in cui la classe annidata SynchronizedList è:

static class SynchronizedList<E> 
extends SynchronizedCollection<E> 
      implements List<E> { 
    private static final long serialVersionUID = -7754090372962971524L; 
    final List<E> list; 

    SynchronizedList(List<E> list) { 
     super(list); 
     this.list = list; 
    } 
    SynchronizedList(List<E> list, Object mutex) { 
     super(list, mutex); 
     this.list = list; 
    } 

    public boolean More ...equals(Object o) { 
     synchronized(mutex) {return list.equals(o);} 
    } 

    //ommited 

    public void add(int index, E element) { 
     synchronized(mutex) {list.add(index, element);} 
    } 

    public E remove(int index) { 
     synchronized(mutex) {return list.remove(index);} 
    } 

    //rest is ommited 
} 

Come si fanno ammirare, la classe useses un private bloccare l'oggetto per garantire la sicurezza del thread. Ma the documentation ci permette di iterare su di esso utilizzando il blocco sull'oggetto restituito dal metodo factory.

E 'indispensabile che l'utente sincronizzare manualmente sul restituita lista quando l'iterazione su di esso:

Quindi, usiamo diverse serrature per l'iterazione e la modifica di lista (add, remove, ecc).

Perché è considerato sicuro?

+0

_Quindi, utilizziamo diversi blocchi per l'iterazione e la modifica della lista_ Che cosa ti fa pensare così? –

+0

@SotiriosDelimanolis Il codice sorgente che ho citato. Nella classe nidificata usiamo sincronizzato (mutex) che non è accessibile dall'esterno. –

risposta

7

Il metodo Collections#synchronizedList

public static <T> List<T> synchronizedList(List<T> list) { 
    return (list instanceof RandomAccess ? 
      new SynchronizedRandomAccessList<>(list) : 
      new SynchronizedList<>(list)); 
} 

utilizza quel singolo costruttore di parametro che si hai mostrato nella sua interrogazione. Questo costruttore invoca il super costruttore che imposta this come mutex. Tutti i metodi sono synchronized su mutex, this.

La documentazione indica che è anche possibile sincronizzare l'istanza durante l'iterazione. Tale riferimento è uguale a this all'interno dei corpi del metodo.

Tutte queste azioni sono (dovrebbe, se lo fai bene) quindi condividendo lo stesso blocco.