Eventwaithandle Studium Multi-Threading von albahari atricle haben. Benötige ich ein Schloss _locker
im folgenden Beispiel? Ich vermute nein, da _message
durch EventWaitHandle
geschützt ist. Habe ich recht?Muss ich eine Sperre benötigen, wenn ich
class TwoWaySignaling
{
static EventWaitHandle _ready = new AutoResetEvent (false);
static EventWaitHandle _go = new AutoResetEvent (false);
static readonly object _locker = new object();
static string _message;
static void Main()
{
new Thread (Work).Start();
_ready.WaitOne(); // First wait until worker is ready
lock (_locker) _message = "ooo";
_go.Set(); // Tell worker to go
_ready.WaitOne();
lock (_locker) _message = "ahhh"; // Give the worker another message
_go.Set();
_ready.WaitOne();
lock (_locker) _message = null; // Signal the worker to exit
_go.Set();
}
static void Work()
{
while (true)
{
_ready.Set(); // Indicate that we're ready
_go.WaitOne(); // Wait to be kicked off...
lock (_locker)
{
if (_message == null) return; // Gracefully exit
Console.WriteLine (_message);
}
}
}
}
Ich kann nicht sehen, auf welche Weise das Entfernen der 'Sperre' die Reihenfolge der Ausführung in diesem Beispiel ändern könnte. – Rotem
Keine Sperre erforderlich. Das Ping-Pong-Verfahren zwischen den beiden AutoResetEvents stellt die Synchronisierung bereit und stellt sicher, dass die Threads nicht gleichzeitig auf die Variable zugreifen können. Der WaitOne() - Aufruf stellt eine Speicherbarriere bereit, die sicherstellt, dass das Variablenupdate für einen anderen Thread sichtbar ist. Diese Art von zufälligen Barrieren sind nicht sehr schön, aber nicht ungewöhnlich. Sie bevorzugen die Verwendung der Barrier-Klasse, deren SignalAndWait() -Methode diesen Code viel leichter verständlich macht. Und ist viel effizienter. Code, den Sie verstehen können, vermeidet das Einfädeln von Fehlern, effizienter Code macht alle glücklich. –