2012-02-23 16 views
7

Se ho una collezione sincronizzato similiè sincronizzato il metodo Collection toArray() sincronizzato?

Collection c = Collections.synchronizedCollection(myCollection);

javadoc per le synchronizedCollection mentiones che iterazione esterna deve essere sincronizzata simili:

synchronized (c) { 
Iterator i = c.iterator(); 
while (i.hasNext()) { 
    process (i.next()); 
} 
} 

Posso supporre che c.toArray() è sincronizzato e quindi nessuno le modifiche alla raccolta avverranno quando il metodo viene eseguito?

o devo per sincronizzarlo così:

synchronized (c) { 
    c.toArray(); 
} 
+0

Da dove proviene 'CollectionUtils'? Questa non è una classe API Java standard. – Jesper

+0

Suppongo che voglia dire 'java.util.Collections', non' CollectionUtils'. – skaffman

+0

È la classe di utilità Apache Commons Collections –

risposta

5

Dal Javadoc per synchronizedCollection:

restituisce un insieme (thread-safe) sincronizzato sostenuto dalla raccolta specificata.

Pertanto, c.toArray() non richiede alcuna sincronizzazione aggiuntiva. Il metodo SynchronizedCollectiontoArray() farà il blocco per te. In sostanza, questo è il punto intero di synchronizedCollection().

Se si desidera confermare che questa lettura del contratto è in accordo con l'implementazione effettiva, vedere GrepCode.

+0

Grazie, questo dice tutto. E GrepCode è fantastico! – artur

+0

assolutamente errato. NON PUOI e NON DEVE fare affidamento sull'implementazione del codice. È necessario affidarsi al contratto fornito, e poiché non sembra esserci un contratto fornito NON si può supporre che sia sincronizzato. – Woot4Moo

+0

@ Woot4Moo I javadoc 'synchronized *' methods 'sono piuttosto generali - vuol dire che non dovremmo mai usarli? Tutto quello che dice veramente è che è sicuro per i thread, ma penso che sia sicuro assumere che questo significhi * tutti * i suoi metodi siano thread-safe. L'avviso/esempio sugli iteratori implica anche che la sicurezza del thread provenga dalla sincronizzazione sull'oggetto restituito. – yshavit

2

Se parli dell'utilità di raccolta di comuni di Apache, la risposta è sì. CollectionUtils.synchronizedCollection(...) restituisce un'istanza di SynchronizedCollection che è toArray() metodo è:

public Object[] toArray() { 
     synchronized (lock) { 
      return collection.toArray(); 
     } 
    } 
+0

Grazie. In realtà intendevo la classe standard 'java.util.Collections'. Ma posso vedere che l'asnwer è lo stesso per entrambi. – artur

1

Non è necessario che, il metodo esegue la sincronizzazione per voi.

0

Se si utilizza java.util.Collections che fa parte dell'API Java Collection standard, tutti i metodi sul SynchronizedCollection restituito vengono sincronizzati, incluso toArray(). Vedi i blocchi di codice qui sotto, presi dal codice sorgente Java in java.util.Collections.SynchronizedCollection.

public Object[] toArray() { 
    synchronized(mutex) {return c.toArray();} 
} 

public <T> T[] toArray(T[] a) { 
    synchronized(mutex) {return c.toArray(a);} 
} 
+0

No. È necessario affidarsi al contratto e non all'implementazione. – Woot4Moo

+0

@ Woot4Moo Sono d'accordo con te sul fatto che non si dovrebbe fare affidamento sull'implementazione, solo sul contratto. I frammenti di codice dal codice sorgente Java erano per dare un'idea più chiara di ciò che sta realmente accadendo. Il JavaDoc afferma chiaramente _Ritorna una collezione sincronizzata (thread-safe) supportata dalla collection_ specificata, che viene interpretata come tutti i metodi sulla collezione restituita sono sincronizzati. Non penso ci sia alcuna ambiguità nei documenti su questo. – IceMan

+0

se leggi il documento completo dichiara chiaramente che l'iterazione deve essere sincronizzata. Se puoi convertire tra strutture di dati senza iterazione, mostrami. – Woot4Moo

0

Sembra che ci sia un grosso malinteso su cui basare l'implementazione del codice sorgente. Questo è falso, devi fare affidamento sul contratto del metodo. Dato che il contratto non esiste, non si può presumere che farà qualcosa, in qualsiasi momento l'implementazione sottostante può cambiare. Ad esempio, guarda la seguente funzione:

/** 
* Returns an empty Collection of Books. 
* 
* 
*/ 
public Collection returnEmptyBooks() 
{ 
    return new HashSet<Book>(); 
} 

Ciò implica che posso restituire tutto ciò che implementa l'interfaccia Collection. Firma e documentazione. Non si può presumere che sia sincronizzato o qualsiasi altra cosa di tale natura. Puoi anche dedurre che non recupererai mai nulla da questo metodo, a meno che il contratto non sia stato violato.

Nel caso nessuno legge i commenti. Qualsiasi conversione da una struttura di dati a un'altra implica l'iterazione. Non è possibile passare da Elenco a Set senza iterare su tutti gli elementi. Lo stesso si applica con una conversione in una matrice. È necessario riempire la matrice ripetendo la struttura dei dati iniziale, pertanto è necessario che sia sincronizzata.

+0

Non credo di aver capito il tuo punto. Se per contratto si intende rigorosamente la firma di un metodo, quindi nell'esempio sopra riportato non è vero che il ritorno di null dal 'returnEmptyBooks()' sta violando il contratto. In effetti qualsiasi metodo che restituisce qualsiasi java.lang.Object può restituire null e potrebbe essere solo una ** convenzione ** per restituire Raccolta vuota e non null. Questa convenzione è specifica per l'implementazione e dal tuo ragionamento non ti dovresti fidare neanche di questo. – artur

+0

@artur Contract indica firma + documentazione. Se si consulta la documentazione fornita, si afferma esplicitamente che restituirà una raccolta vuota di libri. Il mio ragionamento continua a rappresentare un pezzo di codice che invocerebbe ciò per garantire una ricezione vuota e non nulla. Se fosse restituito nulla, sarebbe una violazione del contratto. Ci sono molte più cose che entrano in DbC oltre alle semplici dichiarazioni di funzione. – Woot4Moo

+0

Ti capisco. Ma tornando alla mia domanda iniziale, javadoc dice esplicitamente _returns una raccolta sincronizzata (thread-safe). Sulla base di ciò, non sei ancora contento di poter supporre che toArray() della raccolta retruned sia sincronizzato e protetto da thread? – artur

Problemi correlati