Discussion:
sleep ohne thread
(zu alt für eine Antwort)
Jan Uebernickel
2003-08-09 13:36:38 UTC
Permalink
Hi!

Gibt es sleep nur innerhalb von Thread? Ich möchte nach dem Start eines
Thread das Aufrufende Programm schlafen lassen da der Thread erstmal was
organisieren muß... aber irgendwie finde ich sleep nicht für normla
Funktionen

Gruß,

Jan
--
There are only 10 types of people in the world:
Those who understand binary, and those who don't
Lothar Kimmeringer
2003-08-09 14:13:16 UTC
Permalink
Post by Jan Uebernickel
Gibt es sleep nur innerhalb von Thread? Ich möchte nach dem Start eines
Thread das Aufrufende Programm schlafen lassen da der Thread erstmal was
organisieren muß... aber irgendwie finde ich sleep nicht für normla
Funktionen
sleep ist eine static Methode eines Threads, daher ist die
uebliche Vorgehensweise:

try{
Thread.sleep(10000);
}
catch(InterruptedException ie){}


Gruesse, Lothar
--
Lothar Kimmeringer E-Mail: ***@kimmeringer.de
PGP-encrypted mails preferred (Key-ID: 0x8BC3CD81)

Always remember: The answer is forty-two, there can only be wrong
questions!
Paul Ebermann
2003-08-09 14:40:01 UTC
Permalink
Post by Jan Uebernickel
Gibt es sleep nur innerhalb von Thread? Ich möchte nach dem Start eines
Thread das Aufrufende Programm schlafen lassen da der Thread erstmal was
organisieren muß... aber irgendwie finde ich sleep nicht für normla
Funktionen
(a) Jedes Programm hat mindestens einen Thread -
den, der die main-Methode aufruft. (D.h. jede
Methode läuft in einem Thread ab (wenn überhaupt).)


(b) Thread.sleep() ist eine statische Methode,
kann also "direkt" (ohne ein Thread-Objekt zu
haben) aufgerufen werden (mit dem Klassennamen).

(c) Hier ist das vielleicht nicht die richtige
Methode, da du ja nicht weist, wie lange der
andere Thread für seine "Organisation" braucht.

Da ist vielleicht wait()/notify() besser geeignet,
da du hier solange warten kannst, bis der
andere Thread den ersten benachrichtigt.


Paul
Jan Uebernickel
2003-08-09 15:30:01 UTC
Permalink
Post by Paul Ebermann
(b) Thread.sleep() ist eine statische Methode,
kann also "direkt" (ohne ein Thread-Objekt zu
haben) aufgerufen werden (mit dem Klassennamen).
Schonmal nicht schlecht, werde es vielleicht so versuchen.
Post by Paul Ebermann
(c) Hier ist das vielleicht nicht die richtige
Methode, da du ja nicht weist, wie lange der
andere Thread für seine "Organisation" braucht.
Da ist vielleicht wait()/notify() besser geeignet,
da du hier solange warten kannst, bis der
andere Thread den ersten benachrichtigt.
Aus diesem Grund wollte ich zur synchronisation eine boolean Variable
benutzen:

thread:
start...
blabla...
goon = true...

Hauptprogramm
...
starte thread
while(!goon)
sleep(100);
...

Das ist zwar nicht ganz sauber da der zugriff nicht mit semaphoren
geschützt ist, aber da ich nur einmal drauf warten muß und wenn er kurz
nach dem Abfragen die Variable ändert, dann muß ich eben einmal 100ms zu
viel warten, ich glaube die Zeit habe ich noch... :-)

Aber das mit wait() und notify() interessiert mich ja nun doch. Ich
befürchte jedoch ein mögliches Deadlock, außerdem ist mir nicht ganz
klar wie ich gezielt den einen wartenden erwachen lasse.

Der Thread ist bei mir als Subclass implementiert, da ich globale
Variablen zur Kommunikation brauche.

also

hauptprogramm:
new ownThread
ownThread.run
wait()
...

Thread:
blablabla...
notify()
...

so richtig?

Dann hätte ich aber das Problem, das ich noch einen zweiten Thread habe,
der auch noch läuft, der muß auch ein wenig warten, der würde dann ja
auch wait() machen, wenn ich jetzt notify() aufrufe, wie kann ich
steuern welcher Thread reagiert?

Gruß,

Jan
--
There are only 10 types of people in the world:
Those who understand binary, and those who don't
Steffen Hock
2003-08-09 16:09:07 UTC
Permalink
Post by Jan Uebernickel
also
new ownThread
ownThread.run
wait()
...
blablabla...
notify()
...
so richtig?
nicht ganz:
[um mal in deiner Notation zu bleiben]

hauptprogramm:
new ownThread
ownthread.start <- nicht run
while (!ownthread.goOn)
{
wait
}

thread
constructor : goon = false
...
goon = true
notifyAll
Post by Jan Uebernickel
Dann hätte ich aber das Problem, das ich noch einen zweiten Thread habe,
der auch noch läuft, der muß auch ein wenig warten, der würde dann ja
auch wait() machen, wenn ich jetzt notify() aufrufe, wie kann ich
steuern welcher Thread reagiert?
Das hab ich jetzt nicht ganz verstanden. Wer startet den 2ten Thread?

Generell musst du das notify auf eine Referenz verwenden, welche dann
"geweckt" wird.

Gruß
Steffen
--
Pfeif nicht, wenn du pisst.
Jan Uebernickel
2003-08-09 19:26:22 UTC
Permalink
Post by Steffen Hock
[um mal in deiner Notation zu bleiben]
:-) ist ja nur zur Anschauung...
Post by Steffen Hock
thread
constructor : goon = false
...
goon = true
notifyAll
Post by Jan Uebernickel
Dann hätte ich aber das Problem, das ich noch einen zweiten Thread
habe, der auch noch läuft, der muß auch ein wenig warten, der würde
dann ja auch wait() machen, wenn ich jetzt notify() aufrufe, wie kann
ich steuern welcher Thread reagiert?
Das hab ich jetzt nicht ganz verstanden. Wer startet den 2ten Thread?
War auch das Hauptprogramm, ist aber inzwischen der Schrere zum Opfer
gefallen ;-)
Post by Steffen Hock
Generell musst du das notify auf eine Referenz verwenden, welche dann
"geweckt" wird.
Also um das nochmal zu sehen ob ich das verstanden habe (in Besserer
Notation) und um das deutlich zu machen was ich will.

public class myClass
{
private boolean goon;
private MyThread mythread;
private myClass myclass;

public myClass()
{
mythread = new MyThread();
myclass = this;
}

public start_myClass()
{
mythread.start();
while(!goon)
wait();
// was immer zu tun ist
}

private class myThread extends Thread
{
public myThread()
{
goon = false;
}

public void run()
{
// tue dies und das
goon = true;
myclass.notify();
// mache weiter
}
}
}

Somit erwecke ich doch nur meine Hauptclasse wieder zum leben, richtig?
alle anderen waits() irgendwo anders bleiben davon unberührt...

Gruß,

Jan
--
There are only 10 types of people in the world:
Those who understand binary, and those who don't
Paul Ebermann
2003-08-09 16:27:43 UTC
Permalink
Post by Jan Uebernickel
Post by Paul Ebermann
(c) Hier ist das vielleicht nicht die richtige
Methode, da du ja nicht weist, wie lange der
andere Thread für seine "Organisation" braucht.
Da ist vielleicht wait()/notify() besser geeignet,
da du hier solange warten kannst, bis der
andere Thread den ersten benachrichtigt.
Aus diesem Grund wollte ich zur synchronisation eine boolean Variable
start...
blabla...
goon = true...
Hauptprogramm
...
starte thread
while(!goon)
sleep(100);
...
Das ist zwar nicht ganz sauber da der zugriff nicht mit semaphoren
geschützt ist, aber da ich nur einmal drauf warten muß und wenn er kurz
nach dem Abfragen die Variable ändert, dann muß ich eben einmal 100ms zu
viel warten, ich glaube die Zeit habe ich noch... :-)
Das Problem ist, dass du dich nicht wirklich
darauf verlassen kannst, dass der andere Thread
das updaten der Variable mitbekommt.
Post by Jan Uebernickel
Aber das mit wait() und notify() interessiert mich ja nun doch. Ich
befürchte jedoch ein mögliches Deadlock, außerdem ist mir nicht ganz
klar wie ich gezielt den einen wartenden erwachen lasse.
Der Thread ist bei mir als Subclass implementiert, da ich globale
Variablen zur Kommunikation brauche.
Das "ich brauche globale Variablen" zweifele ich mal an :-)
Tut hier aber nichts zur Sache.
Post by Jan Uebernickel
also
new ownThread
ownThread.run
wait()
...
blablabla...
notify()
...
so richtig?
So ähnlich.

wait() und notify() beziehen sich immer
auf ein Objekt (das, was du mit "objekt."
davor schreibst, bzw. in dessen Methode
du bist). Gleichzeitig musst du auf dieses
Objekt synchronisieren - das stellt sicher,
dass die Aufrufe zueinander passen.
[Das geht mit einem synchronized-Block
oder durch Verwendung einer synchronized-Methode.]

Außerdem musst du das wait() in eine
Schleife stecken, da es vorkommen kann,
dass es "spontan" (ohne ein notify())
aufwacht.


Hauptprogramm:

new ownThread
ownthread.start
synchronized( gemeinsames Objekt)
while (nicht fertig)
gemeinsames Objekt.wait


neuer Thread:

blabla
synchronized( gemeinsames Objekt)
gemeinsames Objekt.notify()
Post by Jan Uebernickel
Dann hätte ich aber das Problem, das ich noch einen zweiten Thread habe,
der auch noch läuft, der muß auch ein wenig warten, der würde dann ja
auch wait() machen, wenn ich jetzt notify() aufrufe, wie kann ich
steuern welcher Thread reagiert?
Du kannst beide Threads auf unterschiedlichen
Objekten warten lassen (dann kannst du exakt
steuern, wer wann aufgeweckt wird).
Wenn beide auf dem selben Objekt warten, kanst
du notifyAll() verwenden, um beide aufzuwecken -
sonst wird ein beliebiger aufgeweckt ...


HTH
Paul
Jan Uebernickel
2003-08-09 19:23:15 UTC
Permalink
Post by Paul Ebermann
Das Problem ist, dass du dich nicht wirklich
darauf verlassen kannst, dass der andere Thread
das updaten der Variable mitbekommt.
Äh, warum nicht? und wenn nicht, wie soll ich die sonst Synchronisieren?
der eine muß ja auf den anderen warten...
Post by Paul Ebermann
Post by Jan Uebernickel
Aber das mit wait() und notify() interessiert mich ja nun doch. Ich
befürchte jedoch ein mögliches Deadlock, außerdem ist mir nicht ganz
klar wie ich gezielt den einen wartenden erwachen lasse.
Der Thread ist bei mir als Subclass implementiert, da ich globale
Variablen zur Kommunikation brauche.
Das "ich brauche globale Variablen" zweifele ich mal an :-)
Tut hier aber nichts zur Sache.
In diesem Fall (ergänzend zum Beispiel das ich auf Steffens Nachricht
geschickt habe):

Der Thread startet einen anderen Process und holt dessen Ein- und
Ausgabestöme. Diese habe ich als übergeordnete Variablen angelegt damit
das Hauptprogramm mit ihnen Arbeiten kann. Wie könnte ich denn sonst mit
dem Thread kommunizieren? Ok, wenn er selber was machen würde könnte
man in einer While-Schleife immer mal prüfen und mit getter und setter
funktionen Arbeiten, aber in meinem Fall wird halt der Prozess gestartet
und dann p.waitFor(). Da steht dann der Thread.

ich kopiere mein Beispiel doch noch mal hier rein um nicht immer hin und
herzuspringen:

public class myClass
{
private boolean goon;
private MyThread mythread;
private myClass myclass;

public myClass()
{
mythread = new MyThread();
myclass = this;
}

public start_myClass()
{
mythread.start();
while(!goon)
wait();
// was immer zu tun ist
}

private class myThread extends Thread
{
public myThread()
{
goon = false;
}

public void run()
{
// tue dies und das
goon = true;
myclass.notify();
// mache weiter
}
}
}
Post by Paul Ebermann
wait() und notify() beziehen sich immer
auf ein Objekt (das, was du mit "objekt."
davor schreibst, bzw. in dessen Methode
Das sollte oben durch wait() in MyClass und myclass.notify()
gewährleistet sein!?
Post by Paul Ebermann
du bist). Gleichzeitig musst du auf dieses
Objekt synchronisieren - das stellt sicher,
dass die Aufrufe zueinander passen.
[Das geht mit einem synchronized-Block
oder durch Verwendung einer synchronized-Methode.]
Ich dachte ich verzichte mal auf das synchronized, dass währe zwar
unbedingt nötig wenn ich mit goon irgendwas machen würde und in der Zeit
niemand anderes an der herumpfuschen darf, aber so schreibt ja nur einer
und ein anderer liest, und das noch in einer Schleife.
Post by Paul Ebermann
Außerdem musst du das wait() in eine
Schleife stecken, da es vorkommen kann,
dass es "spontan" (ohne ein notify())
aufwacht.
hmm, ok, dürfte durch das goon auch geschützt sein.
Post by Paul Ebermann
new ownThread
ownthread.start
synchronized( gemeinsames Objekt)
while (nicht fertig)
gemeinsames Objekt.wait
blabla
synchronized( gemeinsames Objekt)
gemeinsames Objekt.notify()
ok, bis auf das synchronized entspricht das ja meinem Beispiel, aber wie
ich denke nach wie vor, dass das Synchronisieren bei einer Zuweisung
in nur einer Richtung nicht nötig ist, aber ich lasse mich gerne vom
Gegenteil überzeugen.
Post by Paul Ebermann
Post by Jan Uebernickel
Dann hätte ich aber das Problem, das ich noch einen zweiten Thread habe,
der auch noch läuft, der muß auch ein wenig warten, der würde dann ja
auch wait() machen, wenn ich jetzt notify() aufrufe, wie kann ich
steuern welcher Thread reagiert?
Du kannst beide Threads auf unterschiedlichen
Objekten warten lassen (dann kannst du exakt
steuern, wer wann aufgeweckt wird).
Wenn beide auf dem selben Objekt warten, kanst
du notifyAll() verwenden, um beide aufzuwecken -
sonst wird ein beliebiger aufgeweckt ...
Alles klar, habe ich kapiert!

Danke,

Jan
--
There are only 10 types of people in the world:
Those who understand binary, and those who don't
Jan Uebernickel
2003-08-09 19:58:19 UTC
Permalink
Hi!
Post by Jan Uebernickel
Post by Jan Uebernickel
new ownThread
ownthread.start
synchronized( gemeinsames Objekt)
while (nicht fertig)
gemeinsames Objekt.wait
blabla
synchronized( gemeinsames Objekt)
gemeinsames Objekt.notify()
ok, bis auf das synchronized entspricht das ja meinem Beispiel, aber wie
ich denke nach wie vor, dass das Synchronisieren bei einer Zuweisung
in nur einer Richtung nicht nötig ist, aber ich lasse mich gerne vom
Gegenteil überzeugen.
ok ok, ohne synchronized kriege ich hier ständig irgendwelche
Exceptions, ich machs mit.

Danke,

Jan
--
There are only 10 types of people in the world:
Those who understand binary, and those who don't
Bernd Eckenfels
2003-08-09 20:08:11 UTC
Permalink
Post by Jan Uebernickel
ok ok, ohne synchronized kriege ich hier ständig irgendwelche
Exceptions, ich machs mit.
ein wait benoetigt immer den monitor auf das object.

Gruss
Bernd
--
eckes privat - http://www.eckes.org/
Project Freefire - http://www.freefire.org/
Jan Uebernickel
2003-08-09 21:20:09 UTC
Permalink
Hi!
Post by Bernd Eckenfels
Post by Jan Uebernickel
ok ok, ohne synchronized kriege ich hier ständig irgendwelche
Exceptions, ich machs mit.
ein wait benoetigt immer den monitor auf das object.
Hatte ich auch gelesen, dann stand da das man den Monitor mit
synchronized auf das Objekt legen kann, was das aber genau ist habe ich
nicht verstanden.

Gruß,

Jan
--
There are only 10 types of people in the world:
Those who understand binary, and those who don't
Sven Köhler
2003-08-10 00:43:53 UTC
Permalink
Post by Jan Uebernickel
Hatte ich auch gelesen, dann stand da das man den Monitor mit
synchronized auf das Objekt legen kann, was das aber genau ist habe ich
nicht verstanden.
In meinem anderen Posting hatte ich ja schon CriticalSection erwähnt.
Stell dir vor, jedes Objekt wäre eine CriticalSection mit einem
Attribut, welches Thread grade in jeder CriticalSection drin ist.
Man sagt dann, das dieses Thread den Monitor vom Objekt hat. Ein anderes
Thread kann nicht in die CriticalSection. Es gibt daher immer nur ein
Thread was den Monitor von einem Objekt haben kann.

Object lock = new Object();

//kein Monitor
synchronized(lock)
{
//Thread hat Monitor
lock.wait();
//Thread hat Monitor
}
//kein Monitor

wie gesagt, der Code hinter wait() steht lässt sich nur schwer
beschreiben. Hier aber ein Versuch der äquivalent zu obigem code ist:

Object lock = new Object();
lock.enterCS();
try
{
lock.wait();
}
finally
{
lock.leaveCS();
}

wobei wait() ungefähr so aussähe:

public void wait()
{
lock.leaveCS();
try
{
//do something really unexciting
}
finally
{
lock.enterCS();
}
}

CriticalSections haben üblicherweise eine enter-Funktion und eine
leave-Funktion. Üblicherweise hat man auch die Wahl ob man nun wirklich
in die CriticalSection rein möchte und damit das Thread für eine
geweisse Zeit warten. Sowas fehlt in Java noch.
Jan Uebernickel
2003-08-10 07:41:05 UTC
Permalink
Hi!
Post by Sven Köhler
In meinem anderen Posting hatte ich ja schon CriticalSection erwähnt.
Stell dir vor, jedes Objekt wäre eine CriticalSection mit einem
Attribut, welches Thread grade in jeder CriticalSection drin ist.
Man sagt dann, das dieses Thread den Monitor vom Objekt hat. Ein anderes
Thread kann nicht in die CriticalSection. Es gibt daher immer nur ein
Thread was den Monitor von einem Objekt haben kann.
CriticalSections haben üblicherweise eine enter-Funktion und eine
leave-Funktion. Üblicherweise hat man auch die Wahl ob man nun wirklich
in die CriticalSection rein möchte und damit das Thread für eine
geweisse Zeit warten. Sowas fehlt in Java noch.
Also, wenn ich das so als hauptsächlich C Programmierer lese, dann
scheint ein Monitor einem Semaphor zu entsprechen, und die
CriticalSection der von einem Semaphor geschützter Bereich.

richtig?

Gruß,

Jan
--
There are only 10 types of people in the world:
Those who understand binary, and those who don't
Raffael Herzog
2003-08-10 11:18:59 UTC
Permalink
Hi Sven,
Also eine Semaphore ist für mich so ein Ding, welches n Thread in
einen Bereich rein lässt.
,----[ From The Free On-line Dictionary of Computing (09 FEB 02) [foldoc] ]
|
| The classic method for restricting access to shared
| resources (e.g. storage) in a multi-processing environment.
| They were invented by Dijkstra and first used in T.H.E
| operating system.
|
| [...]
|
| P and V stand for Dutch "Proberen", to test, and "Verhogen",
| to increment. The value of a semaphore is the number of
| units of the resource which are free (if there is only one
| resource a "binary semaphore" with values 0 or 1 is used).
|
| [...]
`----

Eine Semaphore kann also n Resourcen unter mehreren Threads
verteilen (->beispielsweise als Teil einer Implementation
eines Connection-Pools). Wenn nur eine Einheit der Resource
durch die Semaphore verwaltet wird (binäre Semaphore), ent-
spricht sie im Prinzip exakt dem Java-Synchronized, mit dem
Unterschied, dass eine Semaphore auch shared und exclusive
Locks anbieten kann. Letzeres (also eine binäre Semaphore
die shared und exclusive Locks verwaltet) wäre dann das, was
auf AmigaOS als Semaphore bezeichnet wird.

Ein Monitor in Java ist also sowas wie eine binäre Semapho-
re, die nur exclusive Locks anbietet. Synchronized ist das
zugehörige Sprachkonstrukt, das benötigt wird, weil man den
Monitor in Java nicht direkt ansprechen kann.


Gruss,

Raffi, wann wird in Java endlich zwischen shared und
exclusive Locks unterschieden?
--
=> Neu im Usenet? Fragen? http://www.use-net.ch/usenet_intro_de.html <=
The difference between theory and practice is that in theory, there is
no difference, but in practice, there is.
Raffael Herzog - ***@raffael.ch - http://www.raffael.ch - ICQ #67961355
Bernd Eckenfels
2003-08-10 14:58:49 UTC
Permalink
Post by Jan Uebernickel
Also, wenn ich das so als hauptsächlich C Programmierer lese, dann
scheint ein Monitor einem Semaphor zu entsprechen, und die
CriticalSection der von einem Semaphor geschützter Bereich.
Naja, also ein thread erhaelt den monitor auf ein object genau dann, wenn er
in einen synchronized block auf diesem object hineinlaeuft. Es kann immer
nur genau ein thread den monitor bekommen. Eine synchronized methode gibt
dir den monitor auf this. Wenn der Monitor schon von einem anderen thread
belegt ist, so bleibst du am synchronize stehen. wait() gibt den monitor ab,
bis es den timeout erreicht hat oder aufgeweckt wird.

Gruss
Bernd
--
eckes privat - http://www.eckes.org/
Project Freefire - http://www.freefire.org/
Paul Ebermann
2003-08-10 01:28:30 UTC
Permalink
Post by Jan Uebernickel
Post by Bernd Eckenfels
Post by Jan Uebernickel
ok ok, ohne synchronized kriege ich hier ständig irgendwelche
Exceptions, ich machs mit.
ein wait benoetigt immer den monitor auf das object.
Hatte ich auch gelesen, dann stand da das man den Monitor mit
synchronized auf das Objekt legen kann, was das aber genau ist habe ich
nicht verstanden.
Das sind so Sachen, die in Büchern seltener erklärt
werden, scheint mir. In der LangSpec steht das drin
(Kapitel 18, glaube ich).

Mein Verständnis (so muss es nicht
implementiert werden, aber so kann
man es sich vorstellen, und das
Ergebnis sollte genauso sein):

- Zu jedem Objekt gehört ein "Monitor".
- Dieser Monitor enthält einen Zähler.
- Diesen Monitor kann zu jedem Zeitpunkt
höchstens ein Thread besitzen.
- Ist der Monitor in Besitz eines Threads,
ist sein Zähler nicht auf 0.
- Ist der Monitor frei, ist sein Zähler
auf 0.
- Ein Thread kann beliebig viele Monitore
besitzen.
- Beim Eintritt in einen synchronized(objekt)-Block
erhält der Thread den Monitor auf "objekt".
* Falls der Monitor frei war, wird sein Zähler
auf 1 gesetzt.
* Falls der Thread den Monitor vorher schon
hatte, wird nur der Monitor-Zähler um 1 erhöht.
* Falls den Monitor zur Zeit jemand anders hat,
muss man eben warten, bis der ihn freigibt.
- Beim Austritt aus einem synchronized-Block
wird der Monitor-Zähler um 1 hinuntergezählt,
ist er bei 0, wird der Monitor freigegeben.
- synchronized-Exemplarmethoden verhalten sich
wie synchronized(this)-Blöcke.
- statische synchronized-Methoden verhalten sich
wie synchronized(Klasse.class)-Blöcke.

- objekt.wait([...]):
- prüft, ob der aktuelle Thread
den Monitor für objekt besitzt.
- Falls nicht, gibt es eine Exception.
- sonst:
* der Monitor für objekt wird freigegeben
(der Zähler auf 0 gesetzt, und der alte
Wert des Zählers gemerkt.)
* der Thread wird schlafengelegt, bis
(a) die angegebene Zeit um ist (falls angegeben)
(b) jemand objekt.notifyAll() aufgerufen hat
(c) jemand objekt.notify() aufgerufen hat und dieser
Thread ausgewählt wurde
(d) jemand dem Thread ein interrupt()
schickt
(e) ein "spontanes Aufwachen" erfolgt
* Der Monitor für objekt wird wiedergeholt
(Dies impliziert eventuelles Warten, bis
dieser frei ist).
* Der Monitor-Zähler wird auf den Wert gesetzt,
den er am Anfang hatte
* Falls (d) der Aufwach-Grund war, wird eine
InterruptedException geworfen

- objekt.notify():
- prüft, ob der aktuelle Thread
den Monitor für objekt besitzt.
- Falls nicht, gibt es eine Exception.
- sonst:
* wähle einen beliebigen Thread aus,
der gerade objekt.wait ausführt
(falls existent)
* wecke diesen nach (c) auf.

- objekt.notifyAll()
- prüft, ob der aktuelle Thread
den Monitor für objekt besitzt.
- Falls nicht, gibt es eine Exception.
- sonst:
* wecke alle Threads, die gerade ein
objekt.wait() ausführen nach (b) auf.


Dazu gehören dann auch noch Punkte, an/vor/nach
denen Variablen-Werte gelesen/geschrieben werden
müssen.

Die Tatsache, dass Synchronisation notwendig ist,
stellt sicher, dass die Menge der wartenden Threads
immer wohldefiniert ist (es kann nicht gleichzeitig
ein Thread mit wait() anfangen und ein anderer ein
notify() auf dem selben Objekt ausführen.


Paul
--
The Java Language Specification: http://java.sun.com/docs/books/jls/index.html
Jan Uebernickel
2003-08-10 07:44:40 UTC
Permalink
Post by Paul Ebermann
Die Tatsache, dass Synchronisation notwendig ist,
stellt sicher, dass die Menge der wartenden Threads
immer wohldefiniert ist (es kann nicht gleichzeitig
ein Thread mit wait() anfangen und ein anderer ein
notify() auf dem selben Objekt ausführen.
So langsam kriege ich eine Vorstellung vom ganzen.

Danke,

Jan
--
There are only 10 types of people in the world:
Those who understand binary, and those who don't
Florian Laws
2003-08-10 21:44:45 UTC
Permalink
Post by Paul Ebermann
- prüft, ob der aktuelle Thread
den Monitor für objekt besitzt.
- Falls nicht, gibt es eine Exception.
* wähle einen beliebigen Thread aus,
der gerade objekt.wait ausführt
(falls existent)
* wecke diesen nach (c) auf.
Hm, das verstehe ich vom Timing noch nicht so ganz.

Thread1 hält den Monitor für Objekt
Thread2 macht Objekt.wait
jetzt ruft Thread1 Objekt.notify() für Thread2 auf.
Thread2 wacht auf, stellt fest, dass Thread1 noch immer
den Monitor für Objekt hält (sonst hätte Thread1 ja nicht notify
aufrufen können) und legt sich wieder schlafen.

Was übersehe ich?

Grüße,

Florian
Paul Ebermann
2003-08-10 22:25:43 UTC
Permalink
Post by Florian Laws
Post by Paul Ebermann
- prüft, ob der aktuelle Thread
den Monitor für objekt besitzt.
- Falls nicht, gibt es eine Exception.
* wähle einen beliebigen Thread aus,
der gerade objekt.wait ausführt
(falls existent)
* wecke diesen nach (c) auf.
Hm, das verstehe ich vom Timing noch nicht so ganz.
Thread1 hält den Monitor für Objekt
Thread2 macht Objekt.wait
jetzt ruft Thread1 Objekt.notify() für Thread2 auf.
Thread2 wacht auf, stellt fest, dass Thread1 noch immer
den Monitor für Objekt hält (sonst hätte Thread1 ja nicht notify
aufrufen können) und legt sich wieder schlafen.
Fast richtig.
Post by Florian Laws
Was übersehe ich?
Thread2 legt sich nicht "schlafen",
sondern wartet, bis er den Monitor für
das Objekt bekommen kann.

(Falls Thread1 "böse" ist und den noch
lange hält, kann wie ein "weiterschlafen"
aussehen ...)


Paul
Florian Laws
2003-08-11 15:26:13 UTC
Permalink
Post by Paul Ebermann
Post by Florian Laws
Was übersehe ich?
Thread2 legt sich nicht "schlafen",
sondern wartet, bis er den Monitor für
das Objekt bekommen kann.
Was ist denn der Unterschied zwischen "warten" und "schlafen"?

Grüße,

Florian
Patrick Roemer
2003-08-11 15:47:05 UTC
Permalink
Hallo,
Wenn der Thread schlaeft, ist er inaktiv (suspended) und kann nur ueber
notify[All](), interrupt() oder ggfs. das Erreichen des Timeout dazu
motiviert werden, seine Arbeit wieder aufzunehmen.
Wenn er wartet, ist er aktiv und muss eben nur den Zugriff auf die
Ressource ergattern, die er zum Weiterarbeiten benoetigt.
Um keine weitere Verwirrung aufkommen zu lassen: 'Warten' und 'schlafen'
sind hier keineswegs die von 'wait()' und 'sleep()' ausgeloesten
Zustaende; ich habe die bisher in diesem Thread verwendete Terminologie
weiterverfolgt: Ein Thread 'schlaeft' nach einem wait() bzw. 'wartet'
darauf, dass er den Monitor erhaelt.

Viele Gruesse,
Patrick
Aljoscha Rittner
2003-08-11 16:06:36 UTC
Permalink
Post by Florian Laws
Post by Paul Ebermann
Post by Florian Laws
Was übersehe ich?
Thread2 legt sich nicht "schlafen",
sondern wartet, bis er den Monitor für
das Objekt bekommen kann.
Was ist denn der Unterschied zwischen "warten" und "schlafen"?
Wenn ich schlafe, könnte ich was verpassen. Wenn ich warte, achte ich
darauf das ich ein Ereignis nicht verpasse.

So ähnlich ist es bei Threads. Mit "schlafen" (Thread#sleep) sagt man
dem Thread, er soll eine bestimmte Zeit an Millisekunden stehen
bleiben, danach geht es ohne äußere Einflüsse weiter.
Wenn er "warten" soll (Object#wait), dann hängt er so lange rum, bis
das entsprechende (äußere) Ereignis kommt (notify).

Gruß,
Josch.
--
"Was ist `Buch`?" "IIRC bedrucktes Papier, frueher in deutschen Wohnzim-
mern meist nur hinter Glas und in gegerbte Schweinehaut eingezwaengt an-
zutreffen. Totaler Anachronismus, wurde gegen Mitte der 90er Jahre durch
manpages, ASCII-, HTML- und PDF-Dokumente ersetzt." (aus de.alt.arnooo)
Bernd Eckenfels
2003-08-11 03:03:44 UTC
Permalink
Post by Florian Laws
Hm, das verstehe ich vom Timing noch nicht so ganz.
Thread1 hält den Monitor für Objekt
Thread2 macht Objekt.wait
nein, t2 kann kein wait machen wenn er den monitor nicht hat. t2 muss den
monitor haben und gibt ihn im wait ab. dann kann t1 ihn bekommen, und t2
wird erst aufgeweckt wenn t1 ihn wieder abgibt.

Gruss
Bernd
--
eckes privat - http://www.eckes.org/
Project Freefire - http://www.freefire.org/
Hauke Ingmar Schmidt
2003-08-11 16:48:47 UTC
Permalink
Moin!
Post by Bernd Eckenfels
Post by Florian Laws
Hm, das verstehe ich vom Timing noch nicht so ganz.
Thread1 hält den Monitor für Objekt
Thread2 macht Objekt.wait
nein, t2 kann kein wait machen wenn er den monitor nicht hat. t2 muss
den monitor haben und gibt ihn im wait ab. dann kann t1 ihn bekommen,
und t2 wird erst aufgeweckt wenn t1 ihn wieder abgibt.
Und t3 wird Gouverneur von Kalifornien.

Bis denn
Hauke Ingmar
Paul Ebermann
2003-08-10 01:00:42 UTC
Permalink
Post by Jan Uebernickel
Post by Paul Ebermann
Das Problem ist, dass du dich nicht wirklich
darauf verlassen kannst, dass der andere Thread
das updaten der Variable mitbekommt.
Äh, warum nicht? und wenn nicht, wie soll ich die sonst Synchronisieren?
der eine muß ja auf den anderen warten...
Das liegt an dem etwas problematischen Speicher-Modell
von Java - der Austausch zwischen den einzelnen Threads
und dem zentralen Speicher kann (wenn man keine
Synchronisation einbaut) beliebig lange verzögert
werden.
Post by Jan Uebernickel
Post by Paul Ebermann
Post by Jan Uebernickel
Aber das mit wait() und notify() interessiert mich ja nun doch. Ich
befürchte jedoch ein mögliches Deadlock, außerdem ist mir nicht ganz
klar wie ich gezielt den einen wartenden erwachen lasse.
Der Thread ist bei mir als Subclass implementiert, da ich globale
Variablen zur Kommunikation brauche.
Das "ich brauche globale Variablen" zweifele ich mal an :-)
Tut hier aber nichts zur Sache.
In diesem Fall (ergänzend zum Beispiel das ich auf Steffens Nachricht
Der Thread startet einen anderen Process und holt dessen Ein- und
Ausgabestöme. Diese habe ich als übergeordnete Variablen angelegt damit
das Hauptprogramm mit ihnen Arbeiten kann. Wie könnte ich denn sonst mit
dem Thread kommunizieren? Ok, wenn er selber was machen würde könnte
man in einer While-Schleife immer mal prüfen und mit getter und setter
funktionen Arbeiten, aber in meinem Fall wird halt der Prozess gestartet
und dann p.waitFor(). Da steht dann der Thread.
Also müsstest du vor dem waitFor den Original-Thread
aufwecken.

(Macht dein Thread nach dem waitFor noch etwas?
Sonst könnte man sich das einfach sparen ...)
Post by Jan Uebernickel
ich kopiere mein Beispiel doch noch mal hier rein um nicht immer hin und
public class myClass
Nur ein Hinweis: Klassennamen schreibt man
üblicherweise groß :-)
Post by Jan Uebernickel
{
private boolean goon;
private MyThread mythread;
private myClass myclass;
public myClass()
{
mythread = new MyThread();
myclass = this;
}
public start_myClass()
{
mythread.start();
while(!goon)
wait();
// was immer zu tun ist
}
private class myThread extends Thread
{
public myThread()
{
goon = false;
}
public void run()
{
// tue dies und das
goon = true;
myclass.notify();
// mache weiter
}
}
}
Post by Paul Ebermann
wait() und notify() beziehen sich immer
auf ein Objekt (das, was du mit "objekt."
davor schreibst, bzw. in dessen Methode
Das sollte oben durch wait() in MyClass und myclass.notify()
gewährleistet sein!?
Prinzipiell sieht das gut aus. Du hast hier
auch nicht, wie vorher behauptet "globale
Variablen" oder "Subklassen" verwendet
(zumindest nicht das, was ich darunter
verstehe). Du hast Exemplarvariablen und
eine innere Klasse.

(Statt der myclass-Variable kannst du übrigens
in der inneren Klasse auch myClass.this verwenden.)
Post by Jan Uebernickel
Post by Paul Ebermann
du bist). Gleichzeitig musst du auf dieses
Objekt synchronisieren - das stellt sicher,
dass die Aufrufe zueinander passen.
[Das geht mit einem synchronized-Block
oder durch Verwendung einer synchronized-Methode.]
Ich dachte ich verzichte mal auf das synchronized, dass währe zwar
unbedingt nötig wenn ich mit goon irgendwas machen würde und in der Zeit
niemand anderes an der herumpfuschen darf, aber so schreibt ja nur einer
und ein anderer liest, und das noch in einer Schleife.
Du musst trotzdem synchronisieren - wait()
und notify funktionieren nämlich nur dann
(sonst gibt es eine IllegalMonitorStateException).
Post by Jan Uebernickel
Post by Paul Ebermann
Außerdem musst du das wait() in eine
Schleife stecken, da es vorkommen kann,
dass es "spontan" (ohne ein notify())
aufwacht.
hmm, ok, dürfte durch das goon auch geschützt sein.
Ja.

[...]
Post by Jan Uebernickel
ok, bis auf das synchronized entspricht das ja meinem Beispiel, aber wie
ich denke nach wie vor, dass das Synchronisieren bei einer Zuweisung
in nur einer Richtung nicht nötig ist, aber ich lasse mich gerne vom
Gegenteil überzeugen.
Wie gesagt, du brauchst es, damit wait()/notify
funktioniert.


Paul
--
Kyrills Engel: http://www.kyrills-engel.de.vu
michael paap
2003-08-10 08:20:17 UTC
Permalink
Mein Problem ist, ich muß sichergehen das der Prozess asynchron
ausgeführt wird, und das scheint soweit ich gelesen habe wenn man nur
den Process startet nicht gegeben zu sein,
Wo hast Du das denn gelesen? Meines Wissens wird ein mit Runtime.exec()
gestarteter Prozess immer in einem eigenen Thread ausgeführt.
Bei mir hält der Prozess ubrigens an, also genau das Problem,
nach dem aufruf steht das ganze Java Programm, mit dem Thread... alles
klar.
Ich habe nicht den gesamten Tread verfolgt: Handelt es sich um das
Problem, dass der neu gestartete Prozess blockiert? Warum blockiert auch
das Java-Programm? Benutzt du Process#waitFor()? Wenn ja, hat das nciht
die Ursache, dass der Prozess nicht in einem eigenen thread gestartet
würde, sondern liegt am Vollaufen der Puffer der Ausgabeströme des
Prozesses. Hast Du das jetzt durch asynchrones Auslesen im Griff?

Gruß,
Michael
--
Sollte ausnahmsweise eine Mail-Antwort auf ein Posting vonnöten sein,
bitte folgende Adresse verwenden: newsreply@<Absender-Domain>.
Jan Uebernickel
2003-08-10 08:45:55 UTC
Permalink
Post by michael paap
Mein Problem ist, ich muß sichergehen das der Prozess asynchron
ausgeführt wird, und das scheint soweit ich gelesen habe wenn man nur
den Process startet nicht gegeben zu sein,
Wo hast Du das denn gelesen? Meines Wissens wird ein mit Runtime.exec()
gestarteter Prozess immer in einem eigenen Thread ausgeführt.
einmal API:
There is no requirement that a process represented by a Process object
execute asynchronously or concurrently with respect to the Java process
that owns the Process object.

Und dann u.a. hier:
http://www.sts.tu-harburg.de/intranet/java/JavaHandbuch3/htrml/k100108.html

Wird waitFor nicht aufgerufen, kann auf aktuellen Betriebssystemen wohl
davon ausgegangen werden, daß das externe Programm parallel zum
Java-Programm gestartet wird und asynchron weiterläuft. Diese Aussage
ist allerdings mit Vorsicht zu genießen, denn spezifiziert ist dieses
Verhalten nicht. Im Zweifel hilft ausprobieren.

Habs ausprobiert kein waitFor() benutzt und der Prozess lief und hielt
das Java Programm an.
Post by michael paap
Ich habe nicht den gesamten Tread verfolgt: Handelt es sich um das
Problem, dass der neu gestartete Prozess blockiert? Warum blockiert auch
das Java-Programm? Benutzt du Process#waitFor()? Wenn ja, hat das nciht
die Ursache, dass der Prozess nicht in einem eigenen thread gestartet
würde, sondern liegt am Vollaufen der Puffer der Ausgabeströme des
Prozesses. Hast Du das jetzt durch asynchrones Auslesen im Griff?
Nein, der neu gestartete Prozess blockiert nicht, da war noch ein
anderes Problem, aber man konnte ihnüber die Konsole noch steuern, das
Java Programm hing in der Zeit genau dort wo der Prozess gestartet wurde
(zumindestens zeigen das die System.out.println()s)
Jetzt benutze ich Process.waitFor() vorher habe ich es nicht benutzt und
er hing trotzdem.
Im Puffer stand nur ein kurzer Satz, nämlich die Aufforderung was
einzugeben, Puffer Vollaufen kann ich deshalb denke ich ausschließen.
Durch den Start im Thread habe ich ja eine definierte asynchronisität
geschaffen und es funktioniert eins a!

Gruß,

Jan
--
There are only 10 types of people in the world:
Those who understand binary, and those who don't
Jan Uebernickel
2003-08-10 09:39:41 UTC
Permalink
Post by Jan Uebernickel
Im Puffer stand nur ein kurzer Satz, nämlich die Aufforderung was
einzugeben, Puffer Vollaufen kann ich deshalb denke ich ausschließen.
Durch den Start im Thread habe ich ja eine definierte asynchronisität
geschaffen und es funktioniert eins a!
Ok, aber Vorsicht: Das Problem, dass der Prozess selbst blockiert, wenn
er entsprechende Mengen Output an STOUT oder STDERR erzeugt, den Du
nicht ausliest, bleibt Dir erhalten.
Ja, aber der Prozess gibt auf jeden Befehl eine Antwort und die lese ich
gleich ein, somit habe ich das im Griff.

Danke,

Jan
--
There are only 10 types of people in the world:
Those who understand binary, and those who don't
Jan Uebernickel
2003-08-10 09:42:45 UTC
Permalink
Post by Jan Uebernickel
Habs ausprobiert kein waitFor() benutzt und der Prozess lief und hielt
das Java Programm an.
Auf welchem BS mit welcher VM? Kannst Du mal ein wenig Code posten, mit
dem sich das evtl. reproduzieren ließe?
Das ist debian Woody mit j2sdk1.4.1_03, den alten Code habe ich nicht
mehr, aber wenn du mir eine eMail schickst kann dich dir mal Zugang zum
CVS geben, da müßte die alte Version gespeichert sein.

Asonsten, der Prozess ist gpg --edit-key .....

Gruß,

Jan
--
There are only 10 types of people in the world:
Those who understand binary, and those who don't
Michael Schierl
2003-08-14 13:56:07 UTC
Permalink
Immer wenn mehrere Threads auf etwas zugreifen, mindestens einer
schreibend, sollte man synchronisieren. Ausnahmen (wie volatile
booleans in zeitkritischen Situationen) bestätigen die Regel.
Bei mir die Ausnahme... ;-)
hast du zeitkritische Situationen?
public class Dekker {
boolean x = true, y = true;
public class Thread1 extends Thread {
public void run() {
x = false;
if (y) System.out.print("Eins ");
}
}
public class Thread2 extends Thread {
public void run() {
y = false;
if (x) System.out.print("Zwei ");
\
}
public void test() {
new Thread1.start();
new Thread2.start();
}
}
eins zwei : nicht klar
zwei eins : auch nicht klar
Wenn die Variablen sauber zugewiesen werden können die letzten beiden
nicht auftreten, wenn man sich aber _in_ _Java_ nicht sicher sein kann
das die Variablen an beide Thread übergeben werden...
Wobei ich das aber nicht verstehe, es sei den die VM legt die neue
Zuordnung von Variablen immer an eine neue Stelle im Speicher ab... denn
wenn die Variablen wirklich im Speicher stehen würden mit fixer Adresse,
so dürften die letzten zwei Fälle nie auftreten.
Die Variablen selber stehen im Speicher mit fixer Adresse. Nun stell
dir aber mal ein Multiprozessorsystem vor mit sagen wir 2 Prozessoren.
Jeder Prozessor hat seinen eigenen Cache, und ein
Cachekohärenzprotokoll sorgt dafür, dass nicht beide Prozessoren
dasselbe Speicherwort im Cache haben können. Speicherzugriffe kosten
ein Vielfaches von Cachezugriffen, deshalb will jede
Programmiersprache (und auch jede JVM) diese möglichst vermeiden.

Und genau aus diesem Grunde merkt die JVM, dass hier mehrere Threads
auf dieselben Variablen zugreifen, sieht dass diese nicht "volatile"
deklariert sind und fängt also an zu optimieren - so dass nachher in
etwa sowas ausgeführt würde:

public class Dekker {
boolean x = true, y = true;

public class Thread1 extends Thread {
public void run() {
boolean threadlocal_x = x, threadlocal_y = y;
threadlocal_x = false;
if(ich_habe_Lust_oder_Zeit_oder_whatever) {
x = threadlocal_x;
}
if (threadlocal_y) System.out.print("Eins ");
x=threadlocal_x;
// threadlocal_y wird nicht verändert.
}
}
public class Thread2 extends Thread {
//analog
}
}

Wenn nun also die beiden Threads auf 2 Prozessoren laufen, haben beide
ihre eigenen Variablen in ihrem eigenen Cache und stören sich nicht
gegenseitig. Wenn die Programme jetzt öfter auf diese Variablen
zugreifen, dürfte der Geschwindigkeitsgewinn auf
Multiprozessormaschinen spürbar werden. Und da Java schnell sein will,
macht es das.

Okay, noch ein paar Spezialitäten von Java:

public class NonAtomicLongs {
public long x = 0;

public class Thread1 extends Thread {
public void run() {
x=0xCAFEBABECAFEBABEL;
}
}

public class Thread2 extends Thread {
public void run() {
x=0xAFFEF00FAFFED00FL;
}
}

public void test() throws InterruptedException {
Thread t1 = new Thread1(), t2 = new Thread2();
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(Long.toHexString(x));
}
}

Welche 4 Werte kann dieses Programm (wenn es nicht gerade eine
InterruptedException wirft) ausgeben?

Michael
--
"New" PGP Key! User ID: Michael Schierl <***@gmx.de>
Key ID: 0x58B48CDD Size: 2048 Created: 26.03.2002
Fingerprint: 68CE B807 E315 D14B 7461 5539 C90F 7CC8
http://home.arcor.de/mschierlm/mschierlm.asc
Michael Schierl
2003-08-14 21:01:38 UTC
Permalink
hmm... wann immer zwei Prozesse auf eine Variable zugreifen, so wird mit
der doch sicher etwas passieren. Ich meine, wenn ich eine Variable
zuweise und die nur auslese dann würde das Verfahren ja Sinn machen,
aber wenn zwei Prozesse die Variable verwenden ist das doch _immer_
störend und würde aufgrund des nicht sofortigen abgleichs doch eher
hemmend als fördernt wirken...
Es gibt auch viele Situationen, in denen die Variable nur einmal am
Anfang zugewiesen wird und dann von vielen Threads nur noch gelesen.
Und da ist das schon von Vorteil so. Und wenn du drauf schreiben
willst, brauchst du in der Regel sowieso synchronized, so what?
Post by Michael Schierl
t1.join();
t2.join();
was ist denn join...
wartet bis der Thread zu Ende ist. Siehe Javadoku...
kann das sein das da eine HexZahl zuviel steht?
Wo?

Michael
--
"New" PGP Key! User ID: Michael Schierl <***@gmx.de>
Key ID: 0x58B48CDD Size: 2048 Created: 26.03.2002
Fingerprint: 68CE B807 E315 D14B 7461 5539 C90F 7CC8
http://home.arcor.de/mschierlm/mschierlm.asc
Jan Uebernickel
2003-08-15 19:47:04 UTC
Permalink
Hi!
Post by Michael Schierl
Es gibt auch viele Situationen, in denen die Variable nur einmal am
Anfang zugewiesen wird und dann von vielen Threads nur noch gelesen.
Und da ist das schon von Vorteil so. Und wenn du drauf schreiben
willst, brauchst du in der Regel sowieso synchronized, so what?
Alles klar.
Post by Michael Schierl
kann das sein das da eine HexZahl zuviel steht?
Wo?
Sorry, hatte dur die Buchstaben gezählt, das letzte ist ein L für
long... somit 16 Hexzahlen und L für Long = 17...

Jan
--
There are only 10 types of people in the world:
Those who understand binary, and those who don't
Sven Köhler
2003-08-10 00:30:19 UTC
Permalink
Post by Jan Uebernickel
Post by Paul Ebermann
(c) Hier ist das vielleicht nicht die richtige
Methode, da du ja nicht weist, wie lange der
andere Thread für seine "Organisation" braucht.
Da ist vielleicht wait()/notify() besser geeignet,
da du hier solange warten kannst, bis der
andere Thread den ersten benachrichtigt.
Aus diesem Grund wollte ich zur synchronisation eine boolean Variable
start...
blabla...
goon = true...
Hauptprogramm
...
starte thread
while(!goon)
sleep(100);
...
Das was du hier betriebst ist Polling vom feinsten. Du schläft ein
weilchen, guckst nach, schläft wieder etc.
Wäre es nicht schöner, wenn der Thread schläft und nur aufgeweckt wird,
wenn sich etwas geändert hat?
Post by Jan Uebernickel
Das ist zwar nicht ganz sauber da der zugriff nicht mit semaphoren
geschützt ist, aber da ich nur einmal drauf warten muß und wenn er kurz
nach dem Abfragen die Variable ändert, dann muß ich eben einmal 100ms zu
viel warten, ich glaube die Zeit habe ich noch... :-)
Es wäre ziemlich sauber, wenn die boolschen Variable - auf die ja nun
von 2 threads aus zugeriffen wird - volatile deklarieren würdest.
Semaphore ist hier auch nicht der richtige Ausdruck. Besser trifft es
Critical Section was sich in Java hinter dem synchronized{}-Konstrukt
versteckt.
Post by Jan Uebernickel
Aber das mit wait() und notify() interessiert mich ja nun doch. Ich
befürchte jedoch ein mögliches Deadlock, außerdem ist mir nicht ganz
klar wie ich gezielt den einen wartenden erwachen lasse.
Nun, du hast Thread A und Thread B. Thread B möchte warten bis Thread A
einen gewissen Status erreich hat. Ich würde das so machen:

class ThreadA
{
boolean ready=false;

public synchronized void waitUntilReady() throws InterruptedException
{
while (!this.ready)
this.wait();
}
private synchronized void signalReady()
{
if (!this.ready)
{
this.ready=true;
this.notifyAll();
}
}
}

class ThreadB
{
public void run()
{
...;
thread_a.waitUntilReady();
...;
}
}

Ein paar Erläuterungen:
- wait() packt man gerne in Schleifen, denn man kann sich nicht oft
sicher sein, ob man wegen dem richtigen Ereignis aufgeweckt wurde. Z.B.
kann man einfach "von außen" die notify-Methode des Thread's aufrufen,
und schon ist wäre die ganze Sache ohne die Schleife aus dem Konzept
gebracht.
- die variable ready braucht hier nicht volatile zu sein, wird nämlich
nur innerhalb von synchronized blöcken eingesetzt.
- wait() und notify() dürfen nur on synchronized blöcken aufgerufen
werden, die sich auf das selbe Objekt wie die wait() und
notify()-Aufrufe beziehen (synchronized methode ist das selbe wie
synchronized(this){} )
- wait() unterbricht die CriticalSection. sonst könnte ich die Methode
signalReady ja gar nicht erst ausgeführt werden.
Jan Uebernickel
2003-08-10 08:09:44 UTC
Permalink
Post by Sven Köhler
Das was du hier betriebst ist Polling vom feinsten. Du schläft ein
weilchen, guckst nach, schläft wieder etc.
Wäre es nicht schöner, wenn der Thread schläft und nur aufgeweckt wird,
wenn sich etwas geändert hat?
In diesem Fall schon, ja...
Post by Sven Köhler
Post by Jan Uebernickel
Das ist zwar nicht ganz sauber da der zugriff nicht mit semaphoren
geschützt ist, aber da ich nur einmal drauf warten muß und wenn er
kurz nach dem Abfragen die Variable ändert, dann muß ich eben einmal
100ms zu viel warten, ich glaube die Zeit habe ich noch... :-)
Es wäre ziemlich sauber, wenn die boolschen Variable - auf die ja nun
von 2 threads aus zugeriffen wird - volatile deklarieren würdest.
Semaphore ist hier auch nicht der richtige Ausdruck. Besser trifft es
Critical Section was sich in Java hinter dem synchronized{}-Konstrukt
versteckt.
Das liegt an dem etwas problematischen Speicher-Modell
von Java - der Austausch zwischen den einzelnen Threads
und dem zentralen Speicher kann (wenn man keine
Synchronisation einbaut) beliebig lange verzögert
werden.
ok, durch das volatile, würde dadurch die angesprochene problematische
Austausch der Speicher ausgeglichen?
Post by Sven Köhler
Nun, du hast Thread A und Thread B. Thread B möchte warten bis Thread A
class ThreadA
{
boolean ready=false;
public synchronized void waitUntilReady() throws InterruptedException
{
while (!this.ready)
this.wait();
}
private synchronized void signalReady()
{
if (!this.ready)
{
this.ready=true;
this.notifyAll();
}
}
}
class ThreadB
{
public void run()
{
...;
thread_a.waitUntilReady();
...;
}
}
Dazu gleich mal eine Frage, verwenden alle Funktionen innerhalb einer
Klasse wenn sie als synchronized deklariert werden den gleichen Monitor?
Post by Sven Köhler
- wait() packt man gerne in Schleifen, denn man kann sich nicht oft
sicher sein, ob man wegen dem richtigen Ereignis aufgeweckt wurde. Z.B.
kann man einfach "von außen" die notify-Methode des Thread's aufrufen,
und schon ist wäre die ganze Sache ohne die Schleife aus dem Konzept
gebracht.
ok.
Post by Sven Köhler
- die variable ready braucht hier nicht volatile zu sein, wird nämlich
nur innerhalb von synchronized blöcken eingesetzt.
ja, alles klar, damit greifen die gezielt auf den Speicherbereich zu.
Post by Sven Köhler
- wait() und notify() dürfen nur on synchronized blöcken aufgerufen
werden, die sich auf das selbe Objekt wie die wait() und
notify()-Aufrufe beziehen (synchronized methode ist das selbe wie
synchronized(this){} )
Alles klar, damit ist meine Frage von oben auch beantwortet :-)
Post by Sven Köhler
- wait() unterbricht die CriticalSection. sonst könnte ich die Methode
signalReady ja gar nicht erst ausgeführt werden.
Alles klar, danke

Jan
--
There are only 10 types of people in the world:
Those who understand binary, and those who don't
Jan Uebernickel
2003-08-10 08:50:41 UTC
Permalink
Eine nichtstatische Methode, die als "synchronized" deklariert ist,
entspricht einem Block, bei dem explizit "this" als das Objekt angegeben
wird, auf dem synchronisiert werden soll. Damit verwenden alle
nichtstatischen Methoden den Monitor des "this-Objekts".
Statische Methoden verwenden den Monitor des class-Objektes, also des
Objekts, welches Du mit this.getClass() erhältst.
Aus dem oben Gesagten folgt, dass als synchronized gekennzeichnete
nichtstatische Methoden mehrerer Exemplare der gleichen Klasse
*unterschiedliche* Objekte zur Synchronisation verwenden.
Moment, wenn die alle das this-Objekt verwenden, verwenden sie doch das
*gleiche* Objekt.

Sonst währen die beiden veschiedenen Funktionen die die gleiche Variable
beschreiben nicht mehr synchroniziert und könnten ineinanderpfushen.

Ein jetzt etwas verwirrter

Jan
--
There are only 10 types of people in the world:
Those who understand binary, and those who don't
michael paap
2003-08-10 09:06:04 UTC
Permalink
Post by Jan Uebernickel
Moment, wenn die alle das this-Objekt verwenden, verwenden sie doch das
*gleiche* Objekt.
"this" ist aber für unterschiedliche Exemplare einer Klasse das
jeweilige Exemplar. Beispiel:

Du hast zwei Objekte (Kunde), die beide eine Referenz auf eine Ressource
(Konto) halten. Wenn Du jetzt die (nichtstatischen) Methoden im Kunden,
welche auf das Konto zugreifen synchronisierst, erreichst Du überhaupt
nichts, weil damit beide auf unterscheidlichen Objekten synchronisiert
sind. Deshalb nimmt man für solche Situationen gerne das class-Objekt.

Gruß,
Michael
--
Sollte ausnahmsweise eine Mail-Antwort auf ein Posting vonnöten sein,
bitte folgende Adresse verwenden: newsreply@<Absender-Domain>.
michael paap
2003-08-10 09:08:02 UTC
Permalink
Post by Jan Uebernickel
Moment, wenn die alle das this-Objekt verwenden, verwenden sie doch das
*gleiche* Objekt.
"this" ist aber für unterschiedliche Exemplare einer Klasse das
jeweilige Exemplar. Beispiel:

Du hast zwei Objekte (Kunde), die beide eine Referenz auf eine Ressource
(Konto) halten. Wenn Du jetzt die (nichtstatischen) Methoden im Kunden,
welche auf das Konto zugreifen synchronisierst, erreichst Du überhaupt
nichts, weil damit beide auf unterscheidlichen Objekten synchronisiert
sind. Gibt interessante Effekte...
Lösen könnte man das, indem man die Methodenrümpfe als Blocks auf dem
class-Objekt synchronisiert (mal ganz davon abgesehen, dass man in so
einem Fall natürlich die Zugriffsmehtoden im *Konto* synchronisieren würde).

Gruß,
Michael
--
Sollte ausnahmsweise eine Mail-Antwort auf ein Posting vonnöten sein,
bitte folgende Adresse verwenden: newsreply@<Absender-Domain>.
Jan Uebernickel
2003-08-10 09:49:00 UTC
Permalink
Post by michael paap
Post by Jan Uebernickel
Moment, wenn die alle das this-Objekt verwenden, verwenden sie doch
das *gleiche* Objekt.
"this" ist aber für unterschiedliche Exemplare einer Klasse das
Du hast zwei Objekte (Kunde), die beide eine Referenz auf eine Ressource
(Konto) halten. Wenn Du jetzt die (nichtstatischen) Methoden im Kunden,
welche auf das Konto zugreifen synchronisierst, erreichst Du überhaupt
nichts, weil damit beide auf unterscheidlichen Objekten synchronisiert
sind. Gibt interessante Effekte...
Lösen könnte man das, indem man die Methodenrümpfe als Blocks auf dem
class-Objekt synchronisiert (mal ganz davon abgesehen, dass man in so
einem Fall natürlich die Zugriffsmehtoden im *Konto* synchronisieren würde).
Ja, alles klar also doch so wie ichs mir dachte, wenn aber beide
Funktionen wie im Beispiel in einer klasse sind und es nur ein Objekt
dieser Klasse existiert und die beiden synchronized Funktionen in diesem
Objekt existieren werden sie richtig synchronisiert.

Aber selbst wenn die funktionen als static definiert werden würden, so
würden sie doch nicht das gleiche Objekt verwenden, oder? Oder welches
würden sie verwenden, es sind doch zwei Objekte...

Ich habe jetzt um das richtig deutlich zu machen in der Klasse ein extra
Objekt zur synchronisation eingebaut.

Danke & Gruß,

Jan
--
There are only 10 types of people in the world:
Those who understand binary, and those who don't
Sven Köhler
2003-08-10 11:03:28 UTC
Permalink
Post by Jan Uebernickel
Ja, alles klar also doch so wie ichs mir dachte, wenn aber beide
Funktionen wie im Beispiel in einer klasse sind und es nur ein Objekt
dieser Klasse existiert und die beiden synchronized Funktionen in diesem
Objekt existieren werden sie richtig synchronisiert.
Wieso engst du deine überlegungen auf den Fall ein, dass nur ein Objekt
existiert?
synchronized-methoden entsprechen ja synchronized(this){} und da der
this-pointer ja für jedes Objekt immer ein anderer ist und sowieso auf
das Objekt selbst zeigt passt das schon.
Post by Jan Uebernickel
Aber selbst wenn die funktionen als static definiert werden würden, so
würden sie doch nicht das gleiche Objekt verwenden, oder? Oder welches
würden sie verwenden, es sind doch zwei Objekte...
Ja, das zu dem Objekt oder der Klasse gehörende class Objekt welches man
Übrigens mit folgendem Konstrukt bekommen kann, ohne getClass() zu benutzen:
Klassenname.class
Post by Jan Uebernickel
Ich habe jetzt um das richtig deutlich zu machen in der Klasse ein extra
Objekt zur synchronisation eingebaut.
Das ist auch eine gute Technik. Macht man auch ganz gerne, weil die
notify() methoden ja public sind und die deswegen Hinz&Kunz aufrufen können.
michael paap
2003-08-10 11:58:27 UTC
Permalink
Post by Jan Uebernickel
Aber selbst wenn die funktionen als static definiert werden würden, so
würden sie doch nicht das gleiche Objekt verwenden, oder? Oder welches
würden sie verwenden, es sind doch zwei Objekte...
Nein, Klassenmethoden werden ja eben nicht auf "this" synchronisiert,
sondern auf dem Class-Objekt von "this".

Gruß,
Michael
--
Sollte ausnahmsweise eine Mail-Antwort auf ein Posting vonnöten sein,
bitte folgende Adresse verwenden: newsreply@<Absender-Domain>.
Sven Köhler
2003-08-10 10:58:19 UTC
Permalink
Post by Jan Uebernickel
Post by Sven Köhler
Es wäre ziemlich sauber, wenn die boolschen Variable - auf die ja nun
von 2 threads aus zugeriffen wird - volatile deklarieren würdest.
Semaphore ist hier auch nicht der richtige Ausdruck. Besser trifft es
Critical Section was sich in Java hinter dem synchronized{}-Konstrukt
versteckt.
Das liegt an dem etwas problematischen Speicher-Modell
von Java - der Austausch zwischen den einzelnen Threads
und dem zentralen Speicher kann (wenn man keine
Synchronisation einbaut) beliebig lange verzögert
werden.
ok, durch das volatile, würde dadurch die angesprochene problematische
Austausch der Speicher ausgeglichen?
Also volatile heißt einfach, dass der Zugriff auf die Variable möglichst
direkt geschiet - ohne Caching oder sonst irgentwas.
volatile verhindert also, das durch das Speichermodell von Java die
Variable sich nie/bzw. erst viel zu spät ändert.

In Praxis brauch man das übrigens unter Windows und Linux nicht
wirklich, denn die Threads legen sich keine lokale Kopie vom Speicher
an. Dennoch mag es Systeme geben, unter denen das passieren kann, und
daher ist volatile nicht zu vernachlässigen!
Hauke Ingmar Schmidt
2003-08-11 16:48:04 UTC
Permalink
Moin!
Post by Sven Köhler
Also volatile heißt einfach, dass der Zugriff auf die Variable
möglichst direkt geschiet - ohne Caching oder sonst irgentwas.
volatile verhindert also, das durch das Speichermodell von Java die
Variable sich nie/bzw. erst viel zu spät ändert.
In Praxis brauch man das übrigens unter Windows und Linux nicht
wirklich, denn die Threads legen sich keine lokale Kopie vom Speicher
an. Dennoch mag es Systeme geben, unter denen das passieren kann, und
daher ist volatile nicht zu vernachlässigen!
War es nicht so, daß volatile auch den atomaren Zugriff auf komplexere
primitive Typen (float, double...) garantiert?

Bis denn
Hauke Ingmar
Paul Ebermann
2003-08-11 21:26:21 UTC
Permalink
Post by Hauke Ingmar Schmidt
War es nicht so, daß volatile auch den atomaren Zugriff auf komplexere
primitive Typen (float, double...) garantiert?
double und long.

Alle anderen (byte, char, int, float, boolean) und
Referenztypen müssen auch so atomar sein.


Paul
Bernd Eckenfels
2003-08-09 17:14:46 UTC
Permalink
Post by Jan Uebernickel
Gibt es sleep nur innerhalb von Thread?
Alles ist ein Thread. D.h. du kannst immer auf dem currentThread sleepen.
Alternativ kannst du auch wait() verwenden.

Gruss
Bernd
--
eckes privat - http://www.eckes.org/
Project Freefire - http://www.freefire.org/
Jan Uebernickel
2003-08-09 19:23:11 UTC
Permalink
Post by Bernd Eckenfels
Alles ist ein Thread. D.h. du kannst immer auf dem currentThread sleepen.
Alternativ kannst du auch wait() verwenden.
Ich denke du meinst auch das Thread.sleep(x) !?

Werde wohl beides verwenden müssen.

Danke,

Jan
--
There are only 10 types of people in the world:
Those who understand binary, and those who don't
Lesen Sie weiter auf narkive:
Suchergebnisse für 'sleep ohne thread' (Newsgroups und Mailinglisten)
25
Antworten
Thread/Net Performance
gestartet 2003-10-21 13:30:52 UTC
de.comp.lang.java
12
Antworten
Thread erneut starten - wie geht's?
gestartet 2004-07-13 09:29:05 UTC
de.comp.lang.java
30
Antworten
USB-Stick entfernen OHNE Mausklick?
gestartet 2004-06-07 09:56:55 UTC
microsoft.public.de.german.win2000.hardware
21
Antworten
Korrekte Nutzung von Timer / Thread.sleep() fuer Frequenzgeneratoren?
gestartet 2004-05-17 20:33:29 UTC
de.comp.lang.java
12
Antworten
Programm für eine bestimmte Zeit anhalten ohne Threads
gestartet 2004-02-19 09:22:03 UTC
de.comp.lang.java
Suchergebnisse für 'sleep ohne thread' (Fragen und Antworten)
5
Antworten
Wie blinken LEDs kontinuierlich ein / aus, während die Ausführung eines Skripts fortgesetzt wird?
gestartet 2015-03-25 03:53:15 UTC
raspberry pi
2
Antworten
Wie 6 Ultraschallsensoren an einen Himbeer-Pi anschließen?
gestartet 2017-01-12 01:30:47 UTC
raspberry pi
2
Antworten
Implementieren Sie eine GPIO-Funktion mit einem Rückruf, der eine Asyncio-Methode aufruft
gestartet 2016-09-06 00:12:50 UTC
raspberry pi
4
Antworten
Relais "Blinken" durch Umschalten der Stifte zwischen Eingang und Ausgang
gestartet 2017-11-18 19:59:25 UTC
raspberry pi
2
Antworten
Warum schlafen? Nein, warum eigentlich aufwachen?
gestartet 2014-09-10 16:21:12 UTC
biologie
Nicht verwandte, aber interessante Themen
14
Antworten
Was tötet Rick in "Auto Erotic Assimilation"?
gestartet 2016-06-09 13:58:44 UTC
5
Antworten
Zweck der Schaltfläche "Alle löschen" in Cabin in the Woods
gestartet 2013-01-23 16:29:08 UTC
7
Antworten
Ende von Donnie Darko
gestartet 2011-12-01 19:15:31 UTC
9
Antworten
War der Chip echt oder falsch?
gestartet 2016-08-19 17:31:25 UTC
5
Antworten
Warum erkennt Blofeld James Bond in "Im Geheimdienst Ihrer Majestät" nicht?
gestartet 2012-10-27 13:16:26 UTC
Loading...