Il thread di HttpSession è sicuro, le operazioni di thread di Attribute sono impostate / ottenute?
-
03-07-2019 - |
Domanda
Inoltre, l'oggetto impostato deve essere thread-safe per garantire che conosciamo lo stato dell'oggetto memorizzato nella sessione.
Inoltre, stavo leggendo sul web che alcuni suggeriscono di usare:
synchronized(session) {
session.setAttribute("abc", "abc");
}
È un suggerimento valido?
Soluzione
No, non sono thread-safe, secondo IBM - Teoria e pratica Java : Tutte le applicazioni Web stateful sono rotte? . Devi sincronizzare.
In che modo HttpSession non è thread-safe dal Java Ranch potrebbe anche essere utile.
Altri suggerimenti
Specifica servlet 2.5:
Più servlet che eseguono la richiesta i thread possono avere accesso attivo a stesso oggetto sessione allo stesso tempo. Il contenitore deve garantire che manipolazione di dati interni strutture che rappresentano la sessione gli attributi vengono eseguiti in a modo sicuro per i thread. Lo sviluppatore ha la responsabilità di threadsafe accesso agli oggetti attributo loro stessi. Questo proteggerà il raccolta di attributi all'interno di Oggetto HttpSession da simultaneo accesso, eliminando l'opportunità affinché un'applicazione lo causi collezione da corrompere.
Questo è sicuro:
// guaranteed by the spec to be safe
request.getSession().setAttribute("foo", 1);
Questo è non sicuro:
HttpSession session = request.getSession();
Integer n = (Integer) session.getAttribute("foo");
// not thread safe
// another thread might be have got stale value between get and set
session.setAttribute("foo", (n == null) ? 1 : n + 1);
Questo è non garantito per essere sicuro:
// no guarantee that same instance will be returned,
// nor that session will lock on "this"
HttpSession session = request.getSession();
synchronized (session) {
Integer n = (Integer) session.getAttribute("foo");
session.setAttribute("foo", (n == null) ? 1 : n + 1);
}
Ho visto questo ultimo approccio raccomandato (incluso nei libri J2EE), ma non è garantito che funzioni secondo le specifiche Servlet. Puoi utilizzare l'ID sessione per creare un mutex , ma deve esserci un approccio migliore.
No. E poiché non vuoi che lo stesso client (con sessione) esegua richieste simultanee, dovresti serializzare queste richieste come AbstractController funziona in Spring MVC
In qualche modo, questo dipende dal design del tuo cliente.
Hai la possibilità, nel tuo web design, che un singolo client abbia più richieste simultanee in sospeso utilizzando la stessa sessione HTTP? Questo sembra difficile da fare a meno che non si colleghi una singola sessione HTTP a più socket. (aka, AJAX) A parte questo, l'accesso HTTP di un determinato client sarà a thread singolo per quanto riguarda il server, il che significa che una singola sessione è effettivamente thread-safe.
La sincronizzazione degli oggetti della sessione renderà l'applicazione più sicura rispetto alle modifiche future che renderanno l'applicazione Web in grado di avere più richieste simultanee, quindi non è una cattiva idea. Nelle moderne implementazioni Java, la sincronizzazione non ha il grande costo che era precedentemente associato ad essa, specialmente quando la sincronizzazione è di solito non consigliata. Se l'applicazione utilizza AJAX, il che implica che ti aspetti più richieste simultanee in volo al tuo server web, la sincronizzazione è un must.
Non lo sono, ma la maggior parte delle volte, i tuoi clienti accederanno a loro solo con un singolo thread.
Client diversi avranno thread diversi e ognuno avrà la propria sessione.
Come sottolinea Eddie, una situazione in cui è possibile affrontare due thread accedendo alla stessa sessione è che due chiamate ajax stanno tentando di modificare lo stesso attributo di sessione. Altrimenti non avrai problemi.
La sessione non è thread-safe e né i metodi get not set sono garantiti come thread safe. In generale in un contenitore servlet dovresti presumere di trovarti in un ambiente multi-thread e nessuna attrezzatura fornita è sicura.
Questo vale anche per gli oggetti che memorizzi nella sessione. La sessione stessa non manipolerà l'oggetto memorizzato ma è possibile recuperarlo in un thread diverso e tentare di manipolarlo. Sta a te esaminare il tuo codice per vedere se le condizioni di gara sono possibili.
L'esempio di codice che hai pubblicato è valido, ma il problema potrebbe esistere oltre l'ambito limitato del tuo esempio. Assicura che non ci siano condizioni durante l'impostazione della sessione, ma nulla impedisce a un altro thread di sovrascrivere il set. Se il codice nella tua richiesta dipende dal valore che rimane invariato, potresti essere ancora nei guai.