Hallo zusammen!
Ich muss mich gerade mit einem Quellcode von einen Server auseinandersetzen und ich glaube dass da irgendwas nicht ganz richting, in Sachen Multithreading, ist:
class TrHandler
{
private object Lock = new Object();
public void senden(int connectionID)
{
lock(Lock)
(new Thread(new ParameterizedThreadStart(waitAndSend))).Start(connectionID));
}
public void waitAndSend(object clientData)
{
Monitor.Enter(Lock);
//tuhe was
Monitor.Exit(Lock);
}
}
Und wenn ich es richtig verstehe, wird durch den folgenden Code:
public void senden(int connectionID)
{
lock(Lock)
(new Thread(new ParameterizedThreadStart(waitAndSend))).Start(connectionID));
}
der ganze Server (wegen der lock(...)-Anweisung) zum Schweigen gebracht, bis die Funktion waitAndSend(..) abgearbeitet ist?
Hallo f.ritz,
nein, nur bis der Thread erzeugt und gestartet ist.
herbivore
Ah, ja! Jetzt verstehe ich!
Ich habe aber noch eine Frage zu diesen Thema - Wenn die Funktion waitAndSend(..) aufgerufen wird, enthält es folgenden Code:
public void waitAndSend(object clientData)
{
int id = (int)clientData;
Monitor.Enter(Lock);
//Mache was mit dem Objekt id
Monitor.Exit(Lock);
}
Kann da nicht was durcheinander, mit dem Objekt id, kommen!?!?!
@f.ritz:
Nein, da die Methode in jedem Thread eine eigene lokale Variable id hat.
Hallo f.ritz,
id ist ja kein Objekt sondern eine Variable. Diese Variable enthält nach der Zuweisung die Referenz, die per Parameter übergeben wurde. Ich sehe nicht, wo da was schief gehen sollte. Wichtig ist ja, die tatsächlichen Zugriffe auf das Objekt selbst zu synchronisieren. Konkurrierende Zugriffe auf die Variable id oder clientData sind ja ausgeschlossen, weil diese nur lokal existieren.
Was mich nur wundert ist, dass an der einen Stelle lock(Lock) und an der anderen Stelle Monitor.Enter(Lock) verwendet wird. Ich denke an beiden (allen) Stellen sollte lock(Lock) verwendet werden.
herbivore
Diese Variable enthält nach der Zuweisung die Referenz
In diesem Fall ja nicht, da int. Daher enthält id eine eigenständige Kopie des Wertes und Synchronisation ist nicht erforderlich.
Hallo Borg,
als ich meine Antwort geschrieben habe, stand da noch MyObject und nicht int. 🙂
herbivore
Original von herbivore
Was mich nur wundert ist, dass an der einen Stelle lock(Lock) und an der anderen Stelle Monitor.Enter(Lock) verwendet wird. Ich denke an beiden (allen) Stellen sollte lock(Lock) verwendet werden.
herbivore
Aber die Wirkung ist doch, unter dem Strich, die Gleiche? Oder?
Original von Borg
Ahhh, der fiese Weg-Editier-Teufel...
Das war doch ein Typisches Multithreading-Problem gerade! 😉
Während ich den Beitrag editiert habe wurden zich Antworten geschrieben 😉
Hallo f.ritz,
ja und nein:
Das lock-Schlüsselwort ruft Monitor.Enter am Anfang des Blocks und Monitor.Exit am Ende des Blocks auf.
Aber zum einen ist der Code schwerer zu verstehen, weil man ihn nur versteht, wenn man weiß, dass es so ist.
Zum anderen denke ich, dass
lock (Lock) {
// Tue was
}
eher
Monitor.Enter (Lock);
try {
// Tue was
}
finally {
Monitor.Exit (Lock);
}
und nicht
Monitor.Enter (Lock);
// Tue was
Monitor.Exit (Lock);
entspricht.
herbivore