2009-03-05 8 views

Antwort

34

Nein, sie sind nicht Thread sicher, nach IBM - Java theory and practice: Are all stateful Web applications broken?. Sie müssen synchronisieren.

How HttpSession is not thread safe von Java Ranch könnte auch hilfreich sein.

+3

Muss Links lesen! ++ – cherouvim

+0

Warum möchten Sie sie synchronisieren? Es gibt eine Sitzung pro Client und Clients sind Single-Threading nicht? – OscarRyz

+1

@Oscar Reyes: Ein Client kann viele gleichzeitige Anfragen ausgeben. zB CTRL + CLICKing (auf Firefox) wie verrückt auf dem Stackoverflow-Logo. – cherouvim

4

Nr Und da Sie nicht den gleichen Client wollen (mit Session) tun gleichzeitige Zugriffe werden, sollten Sie diese Anforderungen serialisiert wie die AbstractController tut in Spring MVC

+1

Ich mochte das Beispiel, aber immer noch ein wenig verwirrt darüber, wie ich das für meine Anwendung verwenden würde. –

2

In gewisser Weise hängt dies von Ihrem Kunden-Design.

Haben Sie in Ihrem Webdesign die Möglichkeit, dass ein einzelner Client mehrere ausstehende gleichzeitige Anforderungen mit derselben HTTP-Sitzung hat? Dies scheint schwierig zu sein, wenn Sie nicht eine einzelne HTTP-Sitzung an mehrere Sockets binden. (aka, AJAX) Kurz gesagt, wird der HTTP-Zugriff eines bestimmten Clients für den Server single-threaded sein, was bedeutet, dass eine einzelne Sitzung effektiv Thread-sicher ist.

Die Synchronisierung Ihrer Sitzungsobjekte macht die Anwendung sicherer vor zukünftigen Änderungen, die Ihre Webanwendung in die Lage versetzen, mehrere gleichzeitige Anforderungen zu erfüllen. Dies ist also keine schlechte Idee. In modernen Java-Implementierungen hat die Synchronisation nicht die großen Kosten, die zuvor damit verbunden waren, insbesondere wenn die Synchronisation in der Regel nicht berücksichtigt wird. Wenn Ihre Anwendung AJAX verwendet, was bedeutet, dass Sie mehrere simultane Anfragen während des Flugs an Ihren Webserver erwarten, ist die Synchronisierung ein Muss.

+0

Ich habe gerade darüber nachgedacht, "synchronyOnSession" für ajax-Anfragen zu deaktivieren, um die Dinge zu beschleunigen (Ajax-Anfragen werden nacheinander ausgeführt, nicht parallel). Also ist es ein großes Nein, nein, dann? Ich dachte, es ist sicher für Ajax, da der Arbeitsablauf normalerweise auf Javascript Seite gesteuert wird. – serg

0

Die Sitzung ist nicht threadsicher und weder die get-Methode noch die set-Methode sind garantiert threadsicher. Im Allgemeinen sollten Sie in einem Servlet-Container davon ausgehen, in einer Umgebung mit mehreren Threads zu sein, und keine bereitgestellten Tools sind sicher.

Dies gilt auch für die Objekte, die Sie in der Sitzung speichern. Die Sitzung selbst wird das gespeicherte Objekt nicht manipulieren, aber Sie können das Objekt in einem anderen Thread abrufen und versuchen, es zu manipulieren. Es liegt an Ihnen, Ihren eigenen Code zu prüfen, um zu sehen, ob Rennbedingungen möglich sind.

Das Codebeispiel, das Sie gepostet haben, ist gültig, aber das Problem kann außerhalb des begrenzten Bereichs Ihres Beispiels bestehen. Es stellt sicher, dass beim Festlegen der Sitzung keine Bedingungen vorhanden sind, aber nichts verhindert, dass ein anderer Thread die Gruppe überschreibt. Wenn der Code in Ihrer Anfrage davon abhängt, dass der Wert unverändert bleibt, könnten Sie immer noch Probleme haben.

61

Servlet 2.5 spec:

Multiple Servlets Anfrage Threads die Ausführung gleichzeitig mit dem gleichen Sitzungsobjekt aktiven Zugriff haben können. Der Container muss sicherstellen, dass die Manipulation der internen Daten Strukturen, die die Sitzung Attribute darstellt, in einer threadsafe Art durchgeführt wird. Der Entwickler hat die Verantwortung für threadsafe Zugriff auf die Attributobjekte selbst.Dies schützt die Attributsammlung innerhalb des HttpSession-Objekts von gleichzeitigem Zugriff , die Möglichkeit für eine Anwendung zu beseitigen, die Auflistung zu verursachen, beschädigt zu werden.

Dies ist sicher:

// guaranteed by the spec to be safe 
request.getSession().setAttribute("foo", 1); 

Diese ist nicht sicher:

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); 

Dies ist nicht garantiert sicher sein:

// 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); 
} 

Ich habe diesen letzten Ansatz befürwortet (einschließlich in J2EE-Büchern), aber es ist nicht garantiert, dass er nach der Servlet-Spezifikation funktioniert. Sie könnten use the session ID to create a mutex, aber es muss einen besseren Ansatz geben.

+0

Versucht zu verstehen, was "Der Container muss sicherstellen, dass die Manipulation von internen Datenstrukturen, die die Sitzungsattribute darstellen, in einer Thread-sicheren Weise ausgeführt wird". Bedeutet das nicht, dass ein Container wie "Tomcat" sicherstellen soll, dass die Methoden getAttribute und setAttribute threadsicher sind? Warum funktioniert der letzte Ansatz nicht? – letronje

+0

@letronje - das bedeutet, dass einzelne Aufrufe von getAttribute/setAttribute threadsicher sein müssen, aber keine Transaktionsgarantien für das Servlet bestehen. Die gleichzeitige Verwendung derselben Sitzung kann daher zu einem inkonsistenten Zustand führen, wenn der Servlet-Entwickler dagegen nicht schützt. – McDowell

+1

@letronje - der letzte Ansatz erfordert, dass die Sitzung auf "this" synchronisiert wird. Das heißt, hat eine Signatur wie 'public syncrhonized void setAttribute ...' oder '... setAttribute (String s, Object o) {synchronisiert (this) ...'. Die Spezifikation erfordert dies nicht. Einige Servlet-Container tun dies, aber es gibt keine Garantien - wie der Container den internen Status schützt, ist ein Implementierungsdetail. – McDowell

1

Sie sind nicht, aber die meisten Ihrer Kunden werden nur mit einem einzigen Thread auf sie zugreifen.

Verschiedene Clients haben unterschiedliche Threads und jeder hat seine eigene Session.

Wie Eddie hervorhebt, sind zwei Ajax-Aufrufe, die versuchen, dasselbe Sitzungsattribut zu ändern, in einer Situation, in der zwei Threads auf dieselbe Sitzung zugreifen können, eine Situation. Sonst wirst du keine Probleme haben.