2013-02-09 9 views
7

da Java Concurrency in practice Capitolo 3.3.3. ThreadLocalConsigli sull'utilizzo di ThreadLocals per avvolgere gli oggetti singoletti mutevoli

variabili thread-local sono spesso utilizzati per prevenire la condivisione in disegni basati su Singletons mutevoli o variabili globali.

Se avvolgiamo il singleton mutabile in un ThreadLocal ogni thread avrà la sua copia del Singleton? Come rimarrà allora un singleton? È questo che intendevano gli autori o mi manca qualcosa di abbastanza ovvio qui?

risposta

2

Se ci avvolgiamo il ragazzo mutabile Singleton in un ThreadLocal

AFAIK non si avvolge la classe singleton con ThreadLocal, ma l'oggetto contenuto all'interno del singleton che è mutabile o non thread safe. Come nell'esempio si illustra correttamente che la connessione JDBC non è thread-safe e richiederà una protezione aggiuntiva, che a sua volta aumenta il conflitto.

Quindi, nei casi in cui i Singleton vengono utilizzati solo allo scopo di condividere, la sostituzione di tali elementi con ThreadLocal è una buona idea, poiché tutti i thread hanno una propria connessione e non è richiesta alcuna protezione aggiuntiva.

Altro buon esempio di utilizzo caso di ThreadLocal è casuale generazione, se v'è un singolo oggetto Random allora c'è contesa all'interno fili per il "seed", quindi se ciascun filo ha il proprio oggetto Random poi ci non c'è più nessuna contesa e questo ha senso.

+0

Che cosa si intende per "voi non avvolgere la classe Singleton con ThreadLocal, ma l'oggetto contenuto all'interno del Singleton, che è mutevole o sicuro non-thread". puoi elaborare per favore? – Geek

+0

Voglio dire che il singleton è un contenitore che usi per condividere l'oggetto. Come un Singleton ConnectionManager verrà utilizzato per condividere l'oggetto di connessione DB. Quindi non si esegue il wrapping del Connection Manager, ma piuttosto si avvolge la connessione in ThreadLocal (Thread Confinement) e quindi si effettua la connessione che era mutabile e non thread-safe, sicura. Spero che abbia senso. –

+0

sì, ha senso. Penso che la citazione nel libro sia ambigua. Cosa ne pensi ? – Geek

0

Se si avvolge un Singleton (come un motivo di progettazione) in un ThreadLocal, esso rimarrà un Singleton. Non c'è una grande magia in un ThreadLocal, se controlli la fonte del ThreadLocal che hai appena visto. Usa una mappa e usa il thread corrente come chiave. Quindi è abbastanza inutile mettere un Singleton (ben implementato) in un ThreadLocal. Come si ottiene lo stesso Singleton in vari modi.

Suppongo che l'autore significhi che se il tuo progetto utilizza pesantemente Singletons e/o variabili globali il ThreadLocal è una buona scelta se hai bisogno di qualcosa di unico per thread e non vuoi passare completamente la gerarchia di chiamata. Ma questa cosa è diversa da una Singleton. Naturalmente si può avere un ThreadLocal incapsulato nel vostro Singleton quindi avrà qualche stato thread specifico (ma che io non lo chiamerei un Singleton più)

0

ciò che ho capito con questa linea è che quando un'applicazione è stata progettata in un modo in cui una classe Singleton ha uno stato mutabile che viene letto e scritto da molti thread richiederà la sicurezza del thread, quindi è necessario serializzare tutti gli accessi a tale stato. Potresti considerare la creazione di un ThreadLocal su quel singleton mutabile. (dal libro :-) Ad esempio, un'applicazione a thread singolo potrebbe mantenere una connessione di database globale inizializzata all'avvio per evitare di dover passare una connessione a ogni metodo. Poiché le connessioni JDBC potrebbero non essere thread-safe, un'applicazione multithread che utilizza una connessione globale senza coordinamento aggiuntivo non è thread-safe. Usando un ThreadLocal per memorizzare la connessione JDBC, come in ConnectionHolder nel Listato 3.10, ogni thread avrà la propria connessione.

private static ThreadLocal<Connection> connectionHolder= new ThreadLocal<Connection>() { 
     public Connection initialValue() { 
    return DriverManager.getConnection(DB_URL); 
    } 
}; 
    public static Connection getConnection() { 
    return connectionHolder.get(); 
    }