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.