Ist das threadsafe?



  • Optimizer schrieb:

    Die Zuweisungen sind nicht zwingend atomar und noch schlimmer, du hast keine Garantie, dass wenn du in einem Thread dein boolean auf true setzt, dass es zeitlich danach im anderen Thread als true ausgelesen wird, es sei denn, du machst es volatile. Ob volatile auch die Zuweisungen atomar macht, weiß ich aber nicht.

    hmm... stimmt. Aber aus reiner Neugier: auch ohne volatile wuerde der Thread die Variable irgendwann neu ins Register einlesen und die Aenderung merken, oder?

    Dein sleep(50) verstehe ich auch nicht. Falls deine Absicht ist, davon auszugehen, dass nach 50 Millisekunden etwas garantiert erledigt ist, muss ich dich enttäuschen.

    Das sleep(50) ist einfach da um die CPU-Auslastung etwas runterzudrehen, die Endlosschleife weckt naemlich immer meinen CPU-Luefter, und das ist nervig 😃

    IMHO gehst du das ganze völlig falsch an, du fragst, ob etwas Thread-safe ist und wenn ich kein einziges Mutex oder Semaphore und kein volatile sehe, ist die Antwort irgendwie nein. Es gibt viele Synchronisationsmöglichkeiten, befasse dich mal damit mit dem synchronized-Schlüsselwort und dem da: http://java.sun.com/developer/JDCTechTips/2005/tt0816.html#2

    Thx fuer den Link. Na ja, ich hab gehofft, dass eine atomare Zuweisung das Problem loesen wuerde. Dass ich den boolean volatile machen sollte seh ich ein. Reicht das, oder sollt ich zusaetzlich noch nicht direkt auf den boolean zugreifen, sondern nur ueber synchronized getter & setter?



  • Blue-Tiger schrieb:

    Optimizer schrieb:

    Die Zuweisungen sind nicht zwingend atomar und noch schlimmer, du hast keine Garantie, dass wenn du in einem Thread dein boolean auf true setzt, dass es zeitlich danach im anderen Thread als true ausgelesen wird, es sei denn, du machst es volatile. Ob volatile auch die Zuweisungen atomar macht, weiß ich aber nicht.

    hmm... stimmt. Aber aus reiner Neugier: auch ohne volatile wuerde der Thread die Variable irgendwann neu ins Register einlesen und die Aenderung merken, oder?

    Wahrscheinlich. Wenn der JIT-Compiler natürlich geil optimiert, dann merkt er, dass sich die Variable "nicht ändert" und eliminiert sie. Wahrscheinlich tut er das nicht.

    Dein sleep(50) verstehe ich auch nicht. Falls deine Absicht ist, davon auszugehen, dass nach 50 Millisekunden etwas garantiert erledigt ist, muss ich dich enttäuschen.

    Das sleep(50) ist einfach da um die CPU-Auslastung etwas runterzudrehen, die Endlosschleife weckt naemlich immer meinen CPU-Luefter, und das ist nervig 😃

    Ui, so ne Warteschleife macht man anders. Besser gesagt keine Schleife, sondern man blockiert den Thread entweder über nen Mutex oder Semaphore. Sieh dir dazu vielleicht mal Object.wait() an.

    Thx fuer den Link. Na ja, ich hab gehofft, dass eine atomare Zuweisung das Problem loesen wuerde. Dass ich den boolean volatile machen sollte seh ich ein. Reicht das, oder sollt ich zusaetzlich noch nicht direkt auf den boolean zugreifen, sondern nur ueber synchronized getter & setter?

    Ehrlich gesagt weiss ich es nicht sicher. Ich würde aber sagen, dass das volatile so ausreicht.



  • Optimizer schrieb:

    Ui, so ne Warteschleife macht man anders. Besser gesagt keine Schleife, sondern man blockiert den Thread entweder über nen Mutex oder Semaphore. Sieh dir dazu vielleicht mal Object.wait()

    Ich versteh glaub ich nicht so ganz, wie man das mit Object.wait() machen koennte 😕 Haettest du eine kleine Denkhilfe? 🙂



  • 79-1



  • Zufälle gibt's, die gibt's nicht mehr.-



  • Blue-Tiger schrieb:

    Optimizer schrieb:

    Ui, so ne Warteschleife macht man anders. Besser gesagt keine Schleife, sondern man blockiert den Thread entweder über nen Mutex oder Semaphore. Sieh dir dazu vielleicht mal Object.wait()

    Ich versteh glaub ich nicht so ganz, wie man das mit Object.wait() machen koennte 😕 Haettest du eine kleine Denkhilfe? 🙂

    naja mit Object.wait() legst du deinen thread schlafen.
    aufwecken tust du mit Object.notify().

    ein sleep() ist wirklich nicht schick. verbrät halt dann doch unnütz
    CPU auch wenn du das deswegen eingebaut hast.
    leg deinen thread schlafen bis er gebraucht wird.
    z.b. bis ein Event gefeuert wird, und dein thread wieder was zu tun hat.



  • atomfish schrieb:

    naja mit Object.wait() legst du deinen thread schlafen.
    aufwecken tust du mit Object.notify().

    ein sleep() ist wirklich nicht schick. verbrät halt dann doch unnütz
    CPU auch wenn du das deswegen eingebaut hast.
    leg deinen thread schlafen bis er gebraucht wird.
    z.b. bis ein Event gefeuert wird, und dein thread wieder was zu tun hat.

    du denkst z. B. dass der Thread auf die "Animationsverwaltungsklasse" wartet, und die ein notify() macht, sobald es Zeit wird, auf's naechste Bild zu wechseln? Also in etwa:

    while (true)
    {
        // warten bis die Animationsklasse bescheid sagt
        actualState.wait();
    
        // zum naechsten Bild wechseln
        ++idx;
        idx %= states.length;
        actualState = states[idx];
    }
    

    Sollte das so gemeint sein: woher weiss dann der "actualState", wann seine Zeit abgelaufen ist? Mir viele da nur ein Timer oder ein sleep() innerhalb der State-Klasse ein, und das wirkt auf mich irgendwie genauso "unschick" wie die sleep()-Loesung. 😕

    Und warum verbraucht sleep() doch unnoetig CPU-Leistung? Weil der Thread oefter aufgeweckt wird als noetig?



  • Ich verstehe die Frage gerade nicht. Du hast doch für deine Sleep-Schleife irgendeine Bedingung, zu der sie verlassen wird. Zu dieser Bedingung sollst du stattdessen notifiy() aufrufen - wenn du es über wait und notify machen willst. Es gibt bessere Wege siehe der Link und die Dokumentation von dem neuen concurrency-Package seit Java 5.
    Eine solche Schleife verbrät etwas CPU-Zeit, weil der Thread öfter aufwacht, was aber eher minimal ist. Wenn du dir mal ansiehst was passiert, wenn du das mit 500 Threads machst, dann ist klar, dass du insgesamt einfach weniger Overhead hast, wenn du die 500 Threads richtig schlafen legst, so dass der Scheduler sie gar nicht erst beachten muss.
    Hauptsächlich würde ich sagen, hast du den Vorteil, dass der Thread bei notify() sofort (und sofort heißt natürlich auch nur, wenn der vom Scheduler versorgt wird) aufwacht und nicht erst nach 50ms. Bei einer GUI-Anwendung kann man solche Verzögerungen spüren und wenn du sie kleiner machst, wird der Overhead durch Einschlafen und Aufwachen wirklich signifikant. Da wait und notify kaum komplizierter zu nutzen ist, würde ich es also tun.



  • Optimizer schrieb:

    Ich verstehe die Frage gerade nicht. Du hast doch für deine Sleep-Schleife irgendeine Bedingung, zu der sie verlassen wird. Zu dieser Bedingung sollst du stattdessen notifiy() aufrufen - wenn du es über wait und notify machen willst. Es gibt bessere Wege siehe der Link und die Dokumentation von dem neuen concurrency-Package seit Java 5.
    Eine solche Schleife verbrät etwas CPU-Zeit, weil der Thread öfter aufwacht, was aber eher minimal ist. Wenn du dir mal ansiehst was passiert, wenn du das mit 500 Threads machst, dann ist klar, dass du insgesamt einfach weniger Overhead hast, wenn du die 500 Threads richtig schlafen legst, so dass der Scheduler sie gar nicht erst beachten muss.
    Hauptsächlich würde ich sagen, hast du den Vorteil, dass der Thread bei notify() sofort (und sofort heißt natürlich auch nur, wenn der vom Scheduler versorgt wird) aufwacht und nicht erst nach 50ms. Bei einer GUI-Anwendung kann man solche Verzögerungen spüren und wenn du sie kleiner machst, wird der Overhead durch Einschlafen und Aufwachen wirklich signifikant. Da wait und notify kaum komplizierter zu nutzen ist, würde ich es also tun.

    Die Klasse dient dazu, eine Animation anzuzeigen, die aus mehreren Bildern besteht. Der Thread dient nur dazu, wenn's soweit ist auf das naechste Bild zu wechseln D.h. die Bedingung dass der thread aufwacht und zum naechsten Bild wechselt, ist dass eine bestimmte Zeit abgelaufen ist. Ueber wait/notify kann ich das also schlecht loesen, weil ich ja wissen muss, wieviel Zeit jeweils vergangen ist, deshalb halt ich sleep() in dem Fall fuer angebracht: in der aktuellen Loesung schlaeft der Thread 25ms, sagt dann der Animationsklasse, dass 25 Sekunden vergangen sind (die Animationsklasse entscheidet dann, ob es bereits Zeit fuer's neue Bild ist) und ruft dann repaint() auf, damit die GUI sich neu zeichnet und evtl. Aenderungen der Animation anzeigt.

    while (isRunning())
    		{
    			try
    			{
    				Thread.sleep(25);
    			}
    			catch (InterruptedException e)
    			{}
    
    			animation.update(25);
    			repaint();
    
    		}
    

    Den Link hab ich mir leider noch nicht durchgelesen, werd ich aber nachholen. Trotzdem scheint mir in meinem Fall meine Loesung eigentlich nicht schlecht. Die einzige Verbesserung, die mir noch einfaellt waere die, den Thread genau solange sleep()-en zu lassen, wie das aktuelle Animationsbild angezeigt werden soll. Das ist im Hinblick auf die Struktur der Animationsklasse aber unguenstig, und den Overhead fuer sinnloses Aufwachen halt ich fuer tragbar, da die Anwendung insgesamt wohl mit 3 Threads auskommen wird.
    Wem trotzdem was eleganteres einfaellt darf sich gern melden. Sonst dank ich fuer die konstruktive Kritik 🙂



  • Ach, du hast praktisch ein festes Zeitintervall bzuwarten. Das ist bei mir nicht schnell genug angekommen.


Anmelden zum Antworten