module MonitorMixin
In der nebenläufigen Programmierung ist ein Monitor ein Objekt oder Modul, das von mehr als einem Thread sicher verwendet werden kann. Das definierende Merkmal eines Monitors ist, dass seine Methoden mit gegenseitigem Ausschluss ausgeführt werden. Das heißt, zu jedem Zeitpunkt darf höchstens ein Thread eine seiner Methoden ausführen. Dieser gegenseitige Ausschluss vereinfacht die Argumentation über die Implementierung von Monitoren im Vergleich zur Argumentation über parallelen Code, der eine Datenstruktur aktualisiert.
Sie können mehr über die allgemeinen Prinzipien auf der Wikipedia-Seite für Monitors lesen.
Beispiele
Einfache Objekt.extend
require 'monitor.rb' buf = [] buf.extend(MonitorMixin) empty_cond = buf.new_cond # consumer Thread.start do loop do buf.synchronize do empty_cond.wait_while { buf.empty? } print buf.shift end end end # producer while line = ARGF.gets buf.synchronize do buf.push(line) empty_cond.signal end end
Der Konsumenten-Thread wartet darauf, dass der Produzenten-Thread eine Zeile in buf pusht, während buf.empty?. Der Produzenten-Thread (Haupt-Thread) liest eine Zeile von ARGF und pusht sie in buf, dann ruft er empty_cond.signal auf, um den Konsumenten-Thread über neue Daten zu benachrichtigen.
Einfache Klasse include
require 'monitor' class SynchronizedArray < Array include MonitorMixin def initialize(*args) super(*args) end alias :old_shift :shift alias :old_unshift :unshift def shift(n=1) self.synchronize do self.old_shift(n) end end def unshift(item) self.synchronize do self.old_unshift(item) end end # other methods ... end
SynchronizedArray implementiert ein Array mit synchronisiertem Zugriff auf Elemente. Diese Klasse wird als Unterklasse von Array implementiert, die das Modul MonitorMixin enthält.
Öffentliche Klassenmethoden
Source
# File ext/monitor/lib/monitor.rb, line 222 def initialize(...) super mon_initialize end
Verwenden Sie extend MonitorMixin oder include MonitorMixin anstelle dieses Konstruktors. Schauen Sie sich die obigen Beispiele an, um zu verstehen, wie dieses Modul verwendet wird.
Öffentliche Instanzmethoden
Source
# File ext/monitor/lib/monitor.rb, line 169 def mon_enter @mon_data.enter end
Gibt den exklusiven Abschnitt ein.
Source
# File ext/monitor/lib/monitor.rb, line 176 def mon_exit mon_check_owner @mon_data.exit end
Verlässt den exklusiven Abschnitt.
Source
# File ext/monitor/lib/monitor.rb, line 184 def mon_locked? @mon_data.mon_locked? end
Gibt true zurück, wenn dieser Monitor von einem beliebigen Thread gesperrt ist
Source
# File ext/monitor/lib/monitor.rb, line 191 def mon_owned? @mon_data.mon_owned? end
Gibt true zurück, wenn dieser Monitor vom aktuellen Thread gesperrt ist.
Source
# File ext/monitor/lib/monitor.rb, line 200 def mon_synchronize(&b) @mon_data.synchronize(&b) end
Gibt den exklusiven Abschnitt ein und führt den Block aus. Der exklusive Abschnitt wird automatisch verlassen, wenn der Block beendet wird. Siehe Beispiel unter MonitorMixin.
Source
# File ext/monitor/lib/monitor.rb, line 160 def mon_try_enter @mon_data.try_enter end
Versucht, den exklusiven Abschnitt einzugeben. Gibt false zurück, wenn die Sperre fehlschlägt.
Source
# File ext/monitor/lib/monitor.rb, line 209 def new_cond unless defined?(@mon_data) mon_initialize @mon_initialized_by_new_cond = true end return ConditionVariable.new(@mon_data) end
Erstellt eine neue MonitorMixin::ConditionVariable, die mit dem Monitor-Objekt verbunden ist.
Private Instanzmethoden
Source
# File ext/monitor/lib/monitor.rb, line 243 def mon_check_owner @mon_data.mon_check_owner end
Stellt sicher, dass der MonitorMixin vom aktuellen Thread besessen wird, andernfalls wird eine Ausnahme ausgelöst.
Source
# File ext/monitor/lib/monitor.rb, line 229 def mon_initialize if defined?(@mon_data) if defined?(@mon_initialized_by_new_cond) return # already initialized. elsif @mon_data_owner_object_id == self.object_id raise ThreadError, "already initialized" end end @mon_data = ::Monitor.new @mon_data_owner_object_id = self.object_id end
Initialisiert das MonitorMixin nach dem Einbinden in eine Klasse oder wenn ein Objekt mit dem MonitorMixin erweitert wurde