next up previous contents index
Search Next: ConditionVariable Up: Koordination von Threads Previous: Koordination von Threads   Contents   Index


Semaphore und die Klasse Mutex

Mit Semaphoren kann der Zugriff auf Ressourcen kontrolliert werden. Sie werden in Multithreaded-Umgebungen verwendet, um Zugriff auf gemeinsame Ressourcen, zum Beispiel Speicherplatz oder gemeinsam genutzte Dateien, zu kontrollieren.

Mutex ist eine Klasse, mit der man einfach Semaphore für jeweils exklusiven Zugriff schreiben kann. Dabei wird ein bestimmtes Objekt für den Zugriff durch andere Threads gesperrt; diese können entweder auf die Freigabe warten oder einen Zugriffsfehler melden. An dieser Stelle muss besonders vorsichtig gearbeitet werden, da sich so genannte "`Deadlocks"' schnell einschleichen, bei denen sich zwei Threads gegenseitig blockieren.

Mutex-Instanzen werden oft verwendet, um Änderungen an gemeinsam genutzten Daten ungestört abwickeln zu können. Inkonsistenzen wegen "`halbaktueller"' Daten können nicht auftreten, da die Aktualisierung effektiv atomar abläuft.

Ein kleines Beispiel: Ein Thread erhöht für 3 Sekunden einen Zähler, auf den ein zweiter gleichzeitig zugreift. Ohne Sperrmechanismus gibt es viele Reste, da die Synchronisation der beiden unabhängigen Schleifen nicht möglich ist.

zahl = rest = 0

zaehler = Thread.new do
  loop do
    13.times { zahl += 1}
  end
end

ueberwacher = Thread.new do
  loop do
    rest += 1 if zahl % 13 != 0
  end
end

sleep 3
printf "Zähler: %d, Reste: %d\n", zahl, rest
#-> Zähler: 1566605, Reste: 701217

Mit einem Mutex-Objekt kann der Zugriff besser kontrolliert werden. Die Methode synchronize sperrt mutex, führt den Codeblock aus und gibt mutex wieder frei. Mittlerweile hat aber der zweite Thread (der ueberwacher) seinen Bedarf angemeldet, so dass sein synchronize-Block abgearbeitet wird, bevor zaehler wieder weiterarbeiten kann. Diese gegenseitigen "`Absprachen"' kosten auch etwas Rechenzeit.

require 'thread'

mutex = Mutex.new
zahl = rest = 0
zaehler = Thread.new do
  loop do
    mutex.synchronize do
      13.times { zahl += 1 }
    end
  end
end

ueberwachen = Thread.new do
  loop do
    mutex.synchronize do
      rest += 1 if zaehler % 13 !=0
    end
  end
end

sleep 3
Thread.critical = true
mutex.lock
printf "Zähler: %d, Reste: %d\n", zahl, rest

#-> Zähler: 1538407, Reste: 0


next up previous contents index
Search Next: ConditionVariable Up: Koordination von Threads Previous: Koordination von Threads   Contents   Index
(C) 2002 by dpunkt.de, Armin Roehrl, Stefan Schmiedl, Clemens Wyss 2002-01-20