Servlet und Threadsicherheit

chickenwings

Erfahrenes Mitglied
Hallo Leute,

bin immer wieder mit dem Thema Threadsicherheit konfrontiert. Teilweise ist es einfach zu erkennen, ob ein Abschnitt Threadsicher ist (bspw. durch synchronized), teilweise ist es aber eben nicht trivial.

Solch einen nicht trivialen Fall habe ich gerade, der zu Diskussionen einlädt. Ich möchte hier einfach mal das Problem abstrakt erörtern, vielleicht hat jemand etwas schlaues dazu zu sagen oder gar Anregungen zur Verbesserung.

Es gibt da ein Servlet, dass mehrere 10tausendmal pro Tag aufgerufen wird. Dieses Servlet nimmt den Request entgegen, validiert einige Paremeter und ruft dann über einen Executors.newSingleThreadExecutor() einen Thread als Service auf, der sich um die Verarbeitung des Requests, bzw. dessen Parameter kümmert. Der Nachteil eines Servlets ist ja, dass der Container eine Menge von Servlets initiiert und dann seine Threads mit diesen Objekten versorgt. Das heisst, jedes Servlet wird mehrmals verwendet.

Die Frage, die sich jetzt stellt ist, ist das Servlet bzw. der eigentliche Service threadsicher? Der Block in dem der Thread über den Executor erzeugt wird ist übrigens nicht synchronisiert.

cheickenwings
 

genodeftest

Erfahrenes Mitglied
Die Frage, die sich jetzt stellt ist, ist das Servlet bzw. der eigentliche Service threadsicher? Der Block in dem der Thread über den Executor erzeugt wird ist übrigens nicht synchronisiert.
Also ist die Erzeugung des Threads wahrscheinlich schon mal unsicher.
Häufiger ist jedoch das Problem, dass von verschiedenen Threads auf das gleiche Objekt zugegriffen wird, und über dieses Objekt bzw. dessen Hierarchie nicht-threadsichere Änderungen durchgeführt werden. Ich vermute für Details brauchen wir den Code…
 

chickenwings

Erfahrenes Mitglied
HI,

der code ist recht simpel:
Code:
doGet(...){
//servlet stuff
...

ExecutorService service = Executors.newSingleThreadExecutor();
try {
final CountDownLatch latch = new CountDownLatch(1);
final ImproveData improver = new ImproveData(!adSpaceTarget, uTID, request, response);
improver.setCL(latch);
if (service != null) {
	service.execute(improver);
	latch.await();
} else {
	LoggingFacade.logException(ViewService.class, "Executor Service was null");
}
} catch (InterruptedException e) {
	LoggingFacade.logException(ViewService.class, e.getMessage());
} finally {
	if (service != null) {
		service.shutdown();
		service = null;
        }
}

...
//other servlet stuff
}

Ist halt die Frage in wie weit ein Servlet Threadsicher ist. Wäre es besser den Executur bzw. dessen Initialisierung zu synchronisieren?


Grüsse,
chickenwings
 

gorefest

Erfahrenes Mitglied
Du kannst Dir imo den Executorservice sparen, wenn Du a) nur lokale Variablen hast oder b) Du nur nach Beans in Deinem Container fragst.

Selbst bei reentranten Funktionen schließt Du damit einen Konflikt aus.

Solltest Du doch Klassenvariablen im Servlet brauchen, solltest Du Dir mal anschauen, was die Kennzeichnung mit volatile macht.

Grüße,
gore
 

chickenwings

Erfahrenes Mitglied
Hallo,

volatile ist mir durchaus ein Begriff, Klassenvariable verwende ich im Servlet nicht.
Den ExecutorService brauche ich, da dieser widerum Threads anstösst, die Berechnungen durchführen, die länger brauchen als der Lebenszyklus eines (dieses) Servlets ist. Meine Idee ist auch, das Servlet so schnell wie möglich freizugeben, damit der nächste Request es benutzen kann, schliesslich hat ein Tomcat nur einen begrenzten Pool von Servlet Instanzen zur Verfügung und die Anzahl der Requests übersteigt diese in jedem Fall.

Daher rührt ja meine Frage, wenn eine Servlet Instanz mehrmals benutzt wird, kann es im dargestellten Block zu Synchronisations-Problemen führen?

Grüsse,
chickenwings