2012-04-21 2 views
5

Quando si legge Head First Servlet and JSP, si dice che la variabile di istanza è non thread-safe.Perché la variabile di istanza in Servlet non è thread-safe

Non capisco questa affermazione così tanto. Ad esempio: ho un servlet il cui nome è ActionServlet.java. Ogni volta, ogni richiesta dell'utente viene inviata al server, il contenitore crea una nuova discussione e crea una nuova istanza ActionServlet.

ActionServlet può essere ha una struttura:

public class ActionServlet extends HttpServlet { 
    // example of instance variable 
    Instance variable; 
    public void processRequest(HttpServletRequest request, HttpServletResponse response) { 
     // process something relating to instance variable 
    } 
} 

Quindi, perché tutti questi fili creano una nuova istanza della classe per ActionServlet, quindi non vedo alcun problema qui. perché le istanze di questi thread sono separate l'una dall'altra.

Si prega di capire dove si trova il problema quando si usa la variabile di istanza nell'ambiente multithread.

Grazie :)

+3

Pensa a chiamare lo stesso metodo sullo stesso oggetto da due thread. –

+0

@DanielFischer Non riesco a immaginare come un thread differente possa utilizzare lo stesso oggetto perché: 1) queste variabili sono private 2) Oggetto di questo thread sempre diverso dall'altro thread (penso). Ho un codice di esempio sopra. Per favore dimmi più chiaro. – hqt

+2

@hqt: il contenitore crea un'istanza univoca del servlet, lo memorizza in una struttura di dati globale (una mappa per esempio) e ogni volta che arriva una richiesta, ottiene il servlet appropriato (basato sul percorso della richiesta) dalla mappa e chiama il suo metodo di servizio. Il fatto che i campi della servlet siano privati ​​non ha alcuna influenza. Il contenitore non si preoccupa nemmeno di loro. –

risposta

14

L'errore si stanno facendo è qui:

Quindi, perché tutti questi fili creano una nuova istanza della classe per ActionServlet, quindi non vedo alcun problema qui. perché le istanze di questi thread sono separate l'una dall'altra.

Il contenitore non crea una nuova istanza della classe Servlet per ogni richiesta. Riutilizza uno esistente. Questo è il motivo per cui non sono thread safe.

The Stripes Action Framework DOES crea una nuova istanza per ogni richiesta, quindi è un presupposto corretto in tale contesto. Tuttavia, ad esempio, Struts 1 segue il modello Servlet e non crea una nuova azione per richiesta.

Ciò non significa che il contenitore sia limitato a una singola istanza, in teoria può creare più di uno, ma non è un comportamento specificato, quindi non può essere considerato affidabile. La maggior parte di quelli popolari no.

+3

In effetti, il contenitore DEVE creare solo un'istanza. Ecco cosa dice la specifica: "Per un servlet non ospitato in un ambiente distribuito (predefinito), il contenitore servlet deve utilizzare solo un'istanza per ogni dichiarazione servlet" –

+0

Oh. Grazie per entrambi @JBNizet e Will Hartung. questo libro non mi mostra che il contenitore SOLO crei solo un'istanza per un servlet. – hqt

0

Il fatto è che il vostro action.java non è istanziato sempre, ma è stato preso da un pool di istanze, lo stesso vale per i fili di richiesta, sono stati presi da un pool di thread , quindi un'istanza servlet può essere condivisa da più richieste.

+4

Non esiste un pool di istanze per servlet. Esiste solo un'istanza servlet per ogni dichiarazione servlet. –

2

perché tutti questi fili creano una nuova istanza della classe (action.java), quindi non vedo alcun problema

Stai supponendo che ogni thread creare un'istanza di classe che verrà utilizzata solo da quel filo, ecco perché non hai nessun problema.

Ma prova ad immaginare, con il tuo campione specifico, che la stessa istanza sia accessibile da due thread. Che cosa succede se entrambi utilizzano nello stesso tempo i tuoi membri request e response? Forse leggerete i dati dalla richiesta non identificabile e scriverete una risposta incoerente che mescola due parti.

Quindi anche in questo caso le variabili di istanza non sono thread-safe, perché se due thread accedono alla stessa istanza possono disturbarsi a vicenda.