class Thread::ConditionVariable
ConditionVariable-Objekte erweitern die Klasse Mutex. Mit Bedingungsvariablen ist es möglich, während eines kritischen Abschnitts zu pausieren, bis eine Bedingung erfüllt ist, z. B. bis eine Ressource verfügbar wird.
Aufgrund der nicht-deterministischen Zeitplanung und falscher Wecksignale sollten Benutzer von Bedingungsvariablen immer ein separates boolesches Prädikat (wie das Lesen aus einer booleschen Variable) verwenden, um zu prüfen, ob die Bedingung tatsächlich erfüllt ist, bevor sie mit dem Warten beginnen. Sie sollten in einer Schleife warten und die Bedingung jedes Mal neu prüfen, wenn die ConditionVariable geweckt wird. Der idiomatische Weg, Bedingungsvariablen zu verwenden, ist der Aufruf der wait-Methode in einer until-Schleife mit dem Prädikat als Schleifenbedingung.
condvar.wait(mutex) until condition_is_met
Im folgenden Beispiel verwenden wir die boolesche Variable resource_available (die durch mutex geschützt wird), um die Verfügbarkeit der Ressource anzuzeigen, und verwenden condvar, um auf das Wahrwerden dieser Variablen zu warten. Beachten Sie, dass
-
Threadbvor den Threadsa1unda2geplant werden kann und so schnell laufen kann, dass er die Ressource bereits verfügbar gemacht hat, bevor entwedera1odera2startet. Daher solltena1unda2prüfen, obresource_availablebereits wahr ist, bevor sie mit dem Warten beginnen. -
Die
wait-Methode kann ohne Signal geweckt werden. Daher sollten die Threadsa1unda2resource_availableerneut prüfen, nachdem diewait-Methode zurückgekehrt ist, und wieder warten, wenn die Bedingung tatsächlich nicht erfüllt ist. -
Es ist möglich, dass Thread
a2direkt nachdem Threada1vonbgeweckt wurde, startet.Threada2hat möglicherweise denmutexerworben und die Ressource verbraucht, bevor Threada1denmutexerwirbt. Dies erfordert auch nachwaiteine erneute Prüfung.
Beispiel
mutex = Thread::Mutex.new resource_available = false condvar = Thread::ConditionVariable.new a1 = Thread.new { # Thread 'a1' waits for the resource to become available and consumes # the resource. mutex.synchronize { condvar.wait(mutex) until resource_available # After the loop, 'resource_available' is guaranteed to be true. resource_available = false puts "a1 consumed the resource" } } a2 = Thread.new { # Thread 'a2' behaves like 'a1'. mutex.synchronize { condvar.wait(mutex) until resource_available resource_available = false puts "a2 consumed the resource" } } b = Thread.new { # Thread 'b' periodically makes the resource available. loop { mutex.synchronize { resource_available = true # Notify one waiting thread if any. It is possible that neither # 'a1' nor 'a2 is waiting on 'condvar' at this moment. That's OK. condvar.signal } sleep 1 } } # Eventually both 'a1' and 'a2' will have their resources, albeit in an # unspecified order. [a1, a2].each {|th| th.join}
Öffentliche Klassenmethoden
Source
# File thread_sync.rb, line 156 def initialize end
Dokument-Methode: ConditionVariable::new
Erstellt eine neue Instanz einer Bedingungsvariable.