Ist gepoolter DB-Zugriff mittels static class thread-safe?
lima-city → Forum → Programmiersprachen → Java
anmerkung
blocken
code
durchlesen
falsche methode
frage
gedanke
methode
null
pool
referenz
setzen
sicherheit
statement
statischen klassen
stattfinden
string
synchronisieren
tausend
zugriff
-
Hi Leute,
komme mit meinen Überlegungen grade nicht zu einer definitiven Aussage.
Einfaches Testen bringts auch nicht, weil sowas tausend Mal gutgehen kann, ein mal mehr hauts dann aber nicht mehr hin.
Habe eine normale Klasse, die DB-Zugriffe über einen connection pool realisiert; diese wird dann natürlich an jeder Stelle, wo DB-Zugriffe stattfinden, erstmal instantiiert.
Um dies einzusparen, möchte ich die Klasse statisch gestalten, sprich, alle Methoden static setzen.
Hier soll es jetzt nicht darum gehen, ob der Gedanke an sich sinnhaft oder ein Singleton sinnvoller ist, sondern nur darum, ob beim static setzen der Methoden die Thread-Sicherheit gewahrt bleibt.
Die static Klasse würde dann so aussehen:
public class DBQuery{ private static String pathToDataSource = ""; private static javax.naming.Context cxt = null; private static javax.sql.DataSource ds = null; private static Connection connect() throws Exception{ if(ds==null){ pathToDataSource = Config.getParam("pathToDataSource"); cxt = new javax.naming.InitialContext(); ds = (javax.sql.DataSource) cxt.lookup(pathToDataSource); } return ds.getConnection(); } public static Vector doDBquery(String querystring){ Vector retVec = new Vector(); Connection connection = null; Statement statement = null; ResultSet resultset = null; try{ connection = getConnection(); statement = connection.createStatement(); resultset = statement.executeQuery(querystring); ... }catch(Exception e){ ... }finally{ // close resultset, statement, connection if not null } return retVec; } } //close class
Da connect() jedesmal eine neue Connection returniert und connection, statement, resultset lokale Variablen auf Methodenebene sind, sollten die Referenzen ja auf dem Stack liegen und damit thread-safe sein, korrekt?
Sprich, wenn tausend Nutzer parallel einen DB-Zugriff starten, sollte meiner Meinung nach nichts in hakeln kommen, da jeder auf seiner eigenen connection arbeitet, aber ist das auch definitiv so oder habe ich irgendetwas übersehen?
Beitrag zuletzt geändert: 11.11.2014 10:15:39 von gcsdriver -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
1) Thread-Sicherheit hat nichts mit
zu tun. War der Code vorher nicht Thread-Sicher, wird er es nachher noch weniger sein.static
2) Wo ist da ein Connection Pool?
3) Warum holst du die Referenz zur
in der static-Methode und nicht beim Initialisieren der Klasse? (und für die die meinen, bei statischen Klassen gäbe es keine Art von Initialisierungsfunktion: doch, gibts)DataSource
4) Wenn du dir um Thread-Sicherheit gedanken machst, solltest du dir das Konzept der Monitore durchlesen und verstehen. Dann würde dir die korrekte Verwendung von
ganz bestimmt auch nicht schwer fallen. Dann hättest du auch Thread-sicheren Code und würdest diese Frage vermutlich nicht stellen müssensynchronized
-
1) Code als dynamische Klasse ist Thread-sicher, denk dir einfach das static vor den Methoden weg
2) hinter der DataSource
3) lazy initialization weil ich nen fauler Hund bin... klar gehts auch im static-Block
4) ich will nicht synchronizen, weil das 999 von 1000 Anfragen zurückstellen würde
-
1) Wieso soll die Klasse, als sie nicht statisch war, thread-sicher gewesen sein? Angenommen du hättest dann von mehreren Threads aus darauf zugegriffen → thread-sicher (und ja, das versteht man unter Thread-Sicherheit: mehrere Threads greifen drauf zu)? Was du eher meinst: »es greift nur ein Thread darauf zu, deshalb ist es egal«.
2) OK.
3) Faulheit ist keine gute Sache. Das bringt dir bezüglich der Thread-Sicherheit sogar einen Nachteil: Stell dir vor, ein Thread greift (indirekt durch
) aufdoDBQuery()
zu, die Funktion hat gerade geprüft obconnect()
und kam zum Schluss, dassds == null
. Sie holt also eine neue DataSource. Genau jetzt kommt ein weiterer Thread, ruft ebenfalls (indirek)ds == null
auf und sieht ebenfallsconnect()
. Auch er holt jetzt die DataSource. In dem Fall wird das egal sein, weil du jeweils die gleiche Referenz bekommst. Sauber ist es dennoch nicht.ds == null
4) Die Frage, die sich dann stellt: kannst du auf die DataSource von mehreren Threads gleichzeitig und sicher auf
zugreifen? Wenn ja → sicher, wenn nein: auf die DataSource dengetConnection()
-Teil synchronisieren (oder diegetConnection()
-Methode selbst). Das ist von der DataSource abhängig. Ich vermute mal, dass du einen Anwendungsserver nutzt, und in diesem Fall ist die DataSource eigentlich immer thread-sicher.connect()
»ich will nicht synchronizen« klingt übrigens irgendwie so, wie wenn du das doch noch nicht so ganz durchschaut hättest … schließlich muss man 1. nicht eine ganze Methode synchronisieren (das würde dann tatsächlich 999 von 1000 blockieren, wenns die falsche Methode ist) und 2. würde, selbst wenn du eine ganze Methode synchronisierst, in deinem Fall das hoffentlich die
-Methode sein, und du würdest somit nicht »999 von 1000 zurückstellen«, sondern dafür sorgen, dass die Threads nacheinander eine Connection bekommen. Die DB-Abfrage passiert dann trotzdem parallel. Beachtest du nun die Ausführungen zu Punkt 4 kannst du dir überlegen, ob du das brauchst oder nicht.connect()
Randbemerkung:
ist ein raw-Typ, du solltest den darin gespeicherten Datentyp vermerken (also z.B.Vector
).Vector<String>
-
Vielen Dank für Deine Anmerkungen,
Du hast ganz recht, das setzen der DataSource ist und war auch vorher als instantiierbare Klasse nicht sicher,
getConnection() sollte aufgrund der Verwendung von org.apache.commons.dbcp kein Thema sein.
Am besten wäre wohl wirklich das Setzen der DataSource im static-Block, werds umschreiben.
Hab Dank für Deine Mühe
-
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage