Ein Objekt von mehreren Threads gleichzeitig benutzt



  • Ein Sache die mir nicht 100%ig klar ist:
    Ich habe zB 3 Threads A,B & C und ein Objekt O von dem es nur ein Objekt/Instanz gibt und das in jedem Thread A,B,C enthalten ist. Nichts im Objekt O ist synchronized! Objekt O greift aber auf eine Datenbank zu und benutzt einen ConnectionPool als Quelle für die Verbindungen zu DB.

    O hat z.B. die Methode:
    public int getNumber() {
    con = getConnectionFromConnectionPool();

    //greife auf die DB zu und mache irgendwas...

    con.close(); //Rückgabe der Verbindung zum Pool
    return number;
    }

    1. Können nun A,B,C gleichzeitig die Methode ausführen? Wie gesagt nichts ist synchronized und das gleichzeitige Ausführen ist erwünscht.
    2. Angenommen A benutzt gerade eine Verbindung aus dem ConnectionPool und ist in getNumber() "drin". Dann kommt B (ist also auch in getNumber() drin) und holt sich einen neue Verbindung aus dem ConnnectionPool. A und B blockieren sich nicht gegenseitig?

    Ich weiß die Fragen sind ziemlich blöd. Aber wie gesagt ich bin mir nicht 100% sicher und wollte mal kurz eure Meinugnen oder Hinweise zur Kenntnis nehmen ;).



  • Das kommt auf die Implementierung des Connection Pools an. Bei einer hinreichend guten Implementierung sollten alle gleichzeitig in der Methode sein und sich nicht blockieren, sofern genug Verbindungen im Pool enthalten sind.



  • Sehr gut. Vielen Dank.



  • ohne synchronisierung können threads eigentlich nicht blockieren, da ja eben die synchronisierung das blockieren auslöst. man sollte nur wissen, dass der scheduler, der threads aktiviert, oder deaktiviert nicht wartet, bis der thread seine aktuelle aktion beendet hat. der scheduler geht allein nach zeit und so kann es passieren, dass ein thread mitten in einem schreibvorgang deaktiviert wird. dann wird ein anderer thread aktiv, schreibt in die selbe variable, wird wieder deaktiviert und der erste thread schreibt nochmal drüber. wenn jetzt ein anderer thread diesen wert liest, steht da praktisch datenmüll. deshalb synchronisiert man... nur lese zugriffe (schreiben kann unter keinen umständen auftreten) müssen nicht gesynct werden.

    wenn du in deiner methode diesen connection pool als ungesynctes objekt hast, das von 3 threads verwendet wird und diese threads in das objekt schreiben (z.b. abfrage string) kann es unter umständen (muss nicht - darüber kann man zu keinem zeitpunkt verlässliche aussagen machen -> undefiniertes verhalten) passieren, dass du wurstabfragen bekommst. dabei ist es egal, ob der connection pool gut implementiert ist. der merkt davon gar nichts.
    ich würde das objekt unbedingt synchronisieren, wenn threads in das objekt in irgendeiner weise schreiben. wenn nur gelesen wird, dann nicht. wenn die methode nur lokale variablen enthält nicht syncen, da der thread seinen eigenen stack hat.

    ich hoffe, ich konnte bissel helfen 😛



  • jule37 schrieb:

    wenn du in deiner methode diesen connection pool als ungesynctes objekt hast, das von 3 threads verwendet wird und diese threads in das objekt schreiben (z.b. abfrage string) kann es unter umständen (muss nicht - darüber kann man zu keinem zeitpunkt verlässliche aussagen machen -> undefiniertes verhalten) passieren, dass du wurstabfragen bekommst. dabei ist es egal, ob der connection pool gut implementiert ist. der merkt davon gar nichts.
    ich würde das objekt unbedingt synchronisieren, wenn threads in das objekt in irgendeiner weise schreiben. wenn nur gelesen wird, dann nicht. wenn die methode nur lokale variablen enthält nicht syncen, da der thread seinen eigenen stack hat.

    ich hoffe, ich konnte bissel helfen 😛

    es ist nicht egal wie der connection-pool programmiert ist. eine vernünftige implementierung wird zusehen dass der connection-pool sich selbst thread-safe macht, also sozusagen intern synchronisiert ist.

    dann kann man den von aussen verwenden wie man mag, ganz ohne synchronisierung.

    und diese threads in das objekt schreiben (z.b. abfrage string)

    WTF?



  • hustbaer schrieb:

    es ist nicht egal wie der connection-pool programmiert ist. eine vernünftige implementierung wird zusehen dass der connection-pool sich selbst thread-safe macht, also sozusagen intern synchronisiert ist.

    dann kann man den von aussen verwenden wie man mag, ganz ohne synchronisierung.

    das sollte dann ja im javadoc der klasse ersichtlich sein, wenn sie wirklich gut designed ist - evtl. ja schon in der methoden signatur.

    hustbaer schrieb:

    und diese threads in das objekt schreiben (z.b. abfrage string)

    WTF?

    ok das beispiel mit dem string war doof; hab grad nicht dran gedacht, dass die ja immutable sind. worauf ich eigentlich hinnaus wollte ist, dass man sich auch thread safe objekte zerschießen kann indem man eigene variablen von den threads manipulieren lässt und dann an methoden des objekts übergibt (besser formuliert?). das war eigentlich was ich meinte mit "dann ist es egal wie der connection pool implementiert ist"...



  • Danke für die Antworten. Der Code war ja irgendwie so:

    public int getNumber() {
    con = getConnectionFromConnectionPool();

    //greife auf die DB zu und mache irgendwas zB Schreiben oder Lesen

    con.close(); //Rückgabe der Verbindung zum Pool
    return number;
    }

    Wenn A und B in der Methode drin sind, dann benutzen beide eine unterschiedliche Verbindung zur Datenbank. Die Datenbankverbindungen untereinander können sich dann erstmal nicht beeinflussen?!



  • was macht die Funktion

    conn= getConnectionFromConnectionPool();
    

    ???

    diese holt sich ne "freie" DB verbindung nehm ich an???

    Wenn diese funktion ordentlich implementiert ist, sorg diese dafür, das jeder thread immer seine eigen verbidung bekommt, und mit close auch jeweis die eigene wieder freigegen wird.

    Aber ich weis nich wie obenstehende Funktion aussieht.



  • Hallo,

    also das arbeiten mit Connection-Pools ist z.B. typisch aus J2EE.
    Bedenke, dass es ausreicht wenn die Methode:

    conn= getConnectionFromConnectionPool();
    

    intern synchronisiert ist, denn sonst (also wenn die Operation nicht atomar ist) könnte ja der Fall eintreten, dass beide Threads dabei sind die gleiche Connection aus dem Connectionpool anzufordern, was nicht sein darf.

    Desweiteren ist noch was anderes ganz wichtig, was mit der Arbeit auf einer Datenbasis ganz wichtig ist: Transaktionen.

    Problem:
    Stelle Dir folgende Situationen vor:
    Sowohl A als auch B haben eine eigene Connection erhalten. In einem weiteren Schritt ändert A mit

    setNumber()
    

    den gleichen Datensatz, welcher von B mittels

    getNumber()
    

    zeitgleich abgefragt wird. Was kriegt nun B zurück; das alte oder das neue? Du hast also eine Dateninkonsistenz.
    Dies war nur ein Beispiel von vielen, wann Dateninkonsistenzen auftreten können.

    Die Lösung des Problems sind die sogenannten Transaktionen.


Anmelden zum Antworten