Markus Möller: Synchronisation bei Servlets

Hallo Forum!
Ich habe eine Frage zu Servelts und was ich dort genau synchronisieren muss. Kleiner Codeschnippsel:

---

public class MyServlet extends HttpServlet {

public myMethod () {
  int i;
  // Hier wird was mit i gemacht
  OtherClass c = OtherClass(this);
  c.doSomeThing();
 }

}

---

public class OtherClass {

HttpServlet mServlet;

public OtherClass(HttpServlet servlet) {
  mServlet = servlet;
 }

public doSomeThing() {
  // Hier wird was mit mServlet gemacht
 }
}

---

Nun meine Frage zu diesem unsinnigen Codefragment. Was muss ich hier in Bezug auf Threads beachten?
In Klasse MyServlet sollte alles OK sein, da sowohl i als auch c lokale Variablen sind. Die werden als nicht von Threads gemeinsam genutzt, oder?
Wie sieht es aber in der anderen Klasse aus? Die hat ja eine Klassenwariable namens mServlet. Könnte das jetzt Probleme geben, so dass ich da etwas synchronisieren muss, oder brauche ich das nicht, weil die Instanz in MyServlet lokal verwendet wird?
Ich hoffe, dass a) meine Fragen verständlich formuliert sind und b) mir jemand eine Antwort drauf geben kann.
Schonmal vielen Dank im Vorraus!

  1. Hi!

    Wie sieht es aber in der anderen Klasse aus? Die hat ja eine Klassenwariable namens mServlet. Könnte das jetzt Probleme geben, so dass ich da etwas synchronisieren muss, oder brauche ich das nicht, weil die Instanz in MyServlet lokal verwendet wird?

    Die Instanz von OtherClass ist zwar eine lokale Variable - hier besteht also kein Problem mit Threads - aber jede Instanz dieser Klasse erhält eine Referenz auf ein und dasselbe Servlet.
    Wenn Du also jetzt von OtherClass aus Felder von mServlet veränderst (sei es direkt durch öffentliche Variablen oder durch Methodenaufrufe), dann können sich dort unterschiedliche Threads in die Quere kommen.

    VG Simon

    1. Hallo und Danke

      Die Instanz von OtherClass ist zwar eine lokale Variable - hier besteht also kein Problem mit Threads - aber jede Instanz dieser Klasse erhält eine Referenz auf ein und dasselbe Servlet.

      Heißt das, das es zur selben Zeit imemr nur genau eine Instanz der Klasse OtherClass gibt?
      In der Praxis übergebe ich nicht das Servlet, sondern das Request-Objekt, um in OtherClass daraus Dinge auszulesen.
      Jetzt stelle ich mir das so vor, dass Benutzer 1 auf das Servlet zugreift und das in seinem Session-Objekt der Benutzername "User1" steht. Benutzer 2 hat "User2" als Name in der Session stehen.
      Nehmen wir an, OtherClass würde jetzt nur "Hallo Benutzer soundso" ausgeben.
      Wenn ich deine Antwort richtig deute, dann könnte der Benutzer 1 mit "User2" begrüßt werden. Ist das richtig?

      1. Hi,

        Hallo und Danke

        Die Instanz von OtherClass ist zwar eine lokale Variable - hier besteht also kein Problem mit Threads - aber jede Instanz dieser Klasse erhält eine Referenz auf ein und dasselbe Servlet.
        Heißt das, das es zur selben Zeit imemr nur genau eine Instanz der Klasse OtherClass gibt?

        Das kommt darauf an - wie weise ;-)).

        Was passiert beim Aufruf eines Servlets? Der Container prüft, ob bereits eine Instanz existiert, und erzeugt eine, falls nicht. Normalerweise gibt es auch _nur eine_ Instanz dieses Servlets in der VM. Wenn jetzt mehrere Client-Requests eintreffen, wird die service()-Methode dieser _einen_ Servlet-Instanz in je einem eigenen Thread aufgerufen.
        Zur selben Zeit gibt es also immer nur eine Instanz der Klasse MyServlet.

        Wieviel Instanzen der Klasse OtherClass gibt es dann?
        Zunächst mal genauso viele wie Aufrufe der Methode myMethod(). Der GarbageCollector wird natürlich wieder einige entfernen. Alles fließt ;-)
        Aber _alle_ Instanzen der Klasse OtherClass halten eine Referenz auf _dieselbe_ Instanz von MyServlet!
        Da alle OtherClass Objekte mittels doSomeThing() etwas mit derselben Servlet-Instanz machen, hast Du genau hier Dein Problem. Du solltest daher das Servlet vor allem dazu verwenden, "herauszufinden", was der Client will ("dispatching"). Das Ausführen der Aktionen solltest Du anderen Objekten (müssen keine Servlets sein) überlassen.

        In der Praxis übergebe ich nicht das Servlet, sondern das Request-Objekt, um in OtherClass daraus Dinge auszulesen.
        Jetzt stelle ich mir das so vor, dass Benutzer 1 auf das Servlet zugreift und das in seinem Session-Objekt der Benutzername "User1" steht. Benutzer 2 hat "User2" als Name in der Session stehen.
        Nehmen wir an, OtherClass würde jetzt nur "Hallo Benutzer soundso" ausgeben.
        Wenn ich deine Antwort richtig deute, dann könnte der Benutzer 1 mit "User2" begrüßt werden. Ist das richtig?

        Nein. Ein HttpServletRequest-Objekt repräsentiert, wie der Name bereits andeutet, einen "Request" des Clienten. Pro "Request" (Klick auf einen Link oder OK-Button eines Formulars etc.) wird vom Container ein HttpServletRequest-Objekt erzeugt bzw. geliefert (wenn Pools verwendet werden) und an die service-Methode des _einen_ Servlet-Objekts übergeben. Ob diese verschiedenen HttpServletRequest-Objekte auch verschiedene Session-Objekte oder dasselbe haben, hängt ganz allgemein von der Instanz des Clienten ab (und wird vollkommen transparent vom Servlet-Container verwaltet).
        Beispiel:
        (A) Wird dasselbe Servlet _kurz hintereinander_ aus demselben Browser(fenster) aufgerufen, handelt es sich um verschiedene HttpServletRequest-Objekte, die aber _dieselbe_ Session besitzen.

        (B) Wird dasselbe Servlet _gleichzeitig_ aus verschiedenen Browsern(instanzen) aufgerufen, handelt es sich um verschiedene HttpServletRequest-Objekte, die auch _unterschiedliche_ Session-Objekte besitzen.

        Also, Benutzer 1 hat "User1" in "seiner" Session stehen, und Benutzer 2 "User2" in "seiner". Das kannst Du allerdings leich ausprobieren.

        So, ich hoffe, dass ich hier sachlich korrekt und hoffentlich verständlich war.

        Viele Grüße,
        Martin