kostenloser Webspace werbefrei: lima-city


Ist gepoolter DB-Zugriff mittels static class thread-safe?

lima-cityForumProgrammiersprachenJava

  1. Autor dieses Themas

    gcsdriver

    Kostenloser Webspace von gcsdriver

    gcsdriver hat kostenlosen Webspace.

    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
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    1) Thread-Sicherheit hat nichts mit
    static
    zu tun. War der Code vorher nicht Thread-Sicher, wird er es nachher noch weniger sein.

    2) Wo ist da ein Connection Pool?

    3) Warum holst du die Referenz zur
    DataSource
    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)

    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
    synchronized
    ganz bestimmt auch nicht schwer fallen. Dann hättest du auch Thread-sicheren Code und würdest diese Frage vermutlich nicht stellen müssen ;-)
  4. Autor dieses Themas

    gcsdriver

    Kostenloser Webspace von gcsdriver

    gcsdriver hat kostenlosen Webspace.

    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
    :wink:
  5. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    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
    doDBQuery()
    ) auf
    connect()
    zu, die Funktion hat gerade geprüft ob
    ds == null
    und kam zum Schluss, dass
    ds == null
    . Sie holt also eine neue DataSource. Genau jetzt kommt ein weiterer Thread, ruft ebenfalls (indirek)
    connect()
    auf und sieht ebenfalls
    ds == null
    . 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.

    4) Die Frage, die sich dann stellt: kannst du auf die DataSource von mehreren Threads gleichzeitig und sicher auf
    getConnection()
    zugreifen? Wenn ja → sicher, wenn nein: auf die DataSource den
    getConnection()
    -Teil synchronisieren (oder die
    connect()
    -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.

    »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
    connect()
    -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.

    Randbemerkung:
    Vector
    ist ein raw-Typ, du solltest den darin gespeicherten Datentyp vermerken (also z.B.
    Vector<String>
    ).
  6. Autor dieses Themas

    gcsdriver

    Kostenloser Webspace von gcsdriver

    gcsdriver hat kostenlosen Webspace.

    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 :thumb:

  7. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!