Wegweiser. Das Erzeuger-/Verbraucher-Problem. Semaphore. Transaktionen. Botschaften

Ähnliche Dokumente
Kritischer Abschnitt. Beispiel: Geld abbuchen. Problem: Wettläufe zwischen den Threads race conditions

leave: mov flag, 0 ; 0 in flag speichern: Lock freigeben ret

Hans-Georg Eßer, Hochschule München Betriebssysteme I, SS Synchronisation (1) Folie 3

Übung zu Grundlagen der Betriebssysteme. 10. Übung

Systeme I: Betriebssysteme Kapitel 5 Nebenläufigkeit und wechselseitiger Ausschluss. Maren Bennewitz

2. Aufgabenblatt Threads

Threads Einführung. Zustände von Threads

Die Anweisungen zweier Prozesse werden parallel bearbeitet, wenn die Anweisungen unabhängig voneinander zur gleichen Zeit ausgeführt werden.

Technische Informatik II

Betriebssysteme. Vorlesung im Herbstsemester 2010 Universität Mannheim. Kapitel 6: Speicherbasierte Prozessinteraktion

Systeme I: Betriebssysteme Kapitel 5 Nebenläufigkeit und wechselseitiger Ausschluss. Maren Bennewitz

#define N 5 // Anzahl der Philosophen. while (TRUE) { // Der Philosoph denkt

Betriebssysteme G: Parallele Prozesse (Teil A: Grundlagen)

Betriebssysteme G: Parallele Prozesse ( Teil C: SpinLock, Semaphore, Monitore)

Prozeßverwaltung. die Prozeßtabelle enthält die Prozeßleitblöcke

Test (Lösungen) Betriebssysteme, Rechnernetze und verteilte Systeme

Thread-Konzept in objektorientierten Programmiersprachen. Threads. Threads in Java

WS Parallele Prozesse. Prof. Hannelore Frank. Parallele Prozesse. PetriNetze. Synchronisation UNIX. Wettbewerb PC Krit.Abschnitt Spinlocks

Betriebssysteme Teil 11: Interprozess-Kommunikation

Parallele Prozesse. Prozeß wartet

Zur Erinnerung: Threads. Threadverwaltung. Threads: Prioritäten. Beispiel Flugbuchungsprogramm. Nichtdeterminismus

Vorlesung Informatik II

Betriebssysteme Theorie

Nebenläufigkeit mit Java

Gegenseitiger Ausschluss 102

Übung Betriebssysteme 11

Prozesse und Prozessmanagement des BS. 1 Unterschied Prozess, Threads. 1.1 Prozess. 1.2 Threads

Verteilte Systeme. Nebenläufigkeit. Prof. Dr. Oliver Haase

Softwaresysteme I Übungen Jürgen Kleinöder Universität Erlangen-Nürnberg Informatik 4, 2007 U9.fm

POSIX-Threads. Aufgabe 9 SP - Ü U10.1

Erstes Leser-Schreiber-Problem

Synchrone Botschaften

JJ Prozesse und Nebenläufigkeit

Betriebssystembau (BSB)

Klausur zur Vorlesung Grundlagen der Betriebssysteme WS 2010 / 2011

Praktische Lernkarten zum Ausschneiden, Zusammenkleben und Sammeln :-) zur Prüfungsvorbereitung Diplomprüfung. Betriebssysteme

U8 POSIX-Threads U8 POSIX-Threads

Linux Prinzipien und Programmierung

Systeme I: Betriebssysteme Kapitel 4 Prozesse. Wolfram Burgard

9. Vorlesung Betriebssysteme

Java Threads. von Gerhart Mende und Awad Fuad. Fuad Awad & Gerhart Mende ProSeminar parallele Programmierung 1

Technische Informatik II

Klausur zur Vorlesung Grundlagen der Betriebssysteme

Nebenläufigkeit in Java. Prof. Dr. Margarita Esponda

RTOS Einführung. Version: Datum: Autor: Werner Dichler

Systemsoftware (SYS) Fakultät für Informatik WS 2007/2008 Christian Baun. Übungsklausur

Erzeuger-Verbraucher-Problem

Softwarelösungen: Versuch 4

U9-3 Vergleich von Thread-Konzepten. U9-2 Motivation von Threads. U9-3 Vergleich von Thread-Konzepten (2) U9-1 Überblick

Prozesse und Scheduling

Klausur Nichtsequentielle Programmierung

Systeme I: Betriebssysteme Kapitel 4 Prozesse. Maren Bennewitz

Aufgaben zum Thema Verklemmungen

B.5 Prozessverwaltung B.5. Prozessverwaltung Prof. Dr. Rainer Manthey Informatik II 1

PThreads. Pthreads. Jeder Hersteller hatte eine eigene Implementierung von Threads oder light weight processes

Infrastruktur und Betriebssysteme III. Martin Plümicke

Literatur. Betriebssysteme - WS 2015/16 - Teil 13/Scheduling 2

Lösung von Übungsblatt 10. (Kommunikation von Prozessen)

CS2101 Nebenläufige und Verteilte Programme Bachelor of Science (Informatik)

Nebenläufige Programmierung

U8-1 Motivation von Threads. U8-2 Vergleich von Thread-Konzepten. U8-2 Vergleich von Thread-Konzepten (2) Motivation

Nebenläufigkeit und Asynchronizität in eingebetteten Systemen. Klaus Kusche, September 2012

Rainer Oechsle. Parallele und verteilte. Anwendungen in Java. 4., neu bearbeitete Auflage. Mit 165 Listings, 5 Tabellen und 71 HANSER

3.2 Prozessumschaltung

5. Threads, Serverprozesse und Benachrichtigungen

Inhaltsverzeichnis. Carsten Vogt. Nebenläufige Programmierung. Ein Arbeitsbuch mit UNIX/Linux und Java ISBN:

Programme werden durch den Ablauf eines oder mehrerer Prozesse (engl.: process, task) von einem Rechner abgearbeitet.

Nebenläufigkeit mit Java

Systemsoftware (SYS) Fakultät für Informatik WS 2008/2009 Christian Baun. Übungsklausur

Gliederung. Monitor (eine auf ein Modul bezogene) Klasse

e) Welche Aussage zu Speicherzuteilungsverfahren ist falsch?

I Grundlagen der parallelen Programmierung 1

Thread-Synchronisation in in Java. Threads Wechselseitiger Ausschluss Bedingte Synchronisation Beispiel: Warteschlangen

Ausnahmebehandlung in Java

Prozesse. Prozesse sind Programme. Prozesse können aus Unterprozessen bestehen. Prozesshierarchie Unterprozesse Threads

Modul B-PRG Grundlagen der Programmierung 1

Operating System Kernels

Übung zu Grundlagen der Betriebssysteme. 7. Übung

Versuchsziele. Grundlagen. Überblick: FB Automatisierung und Informatik Betriebssysteme Thema: Bounded-Buffer-Problem. 3.

9. Foliensatz Betriebssysteme

(Prüfungs-)Aufgaben zum Thema Synchronisation

Markus Klußmann, Amjad Saadeh Institut für Informatik. Pthreads. von Markus Klußmann und Amjad Saadeh. Pthreads

Architektur Verteilter Systeme Teil 6: Interprozess-Kommunikation

Klausur zur Vorlesung Grundlagen Betriebssysteme und Systemsoftware

Betriebssysteme (BTS)

Linked Lists The Role of Locking

Philosophen-Problem mit Threads 99

Systeme 1. Kapitel 6. Nebenläufigkeit und wechselseitiger Ausschluss

Klausur Echtzeitsysteme

Domänenmodell: Fadenkommunikation und -synchronisation

Betriebssysteme I WS 2015/2016. Betriebssysteme / verteilte Systeme Tel.: 0271/ , Büro: H-B 8404


U6-1 Organisatories. U6-2 Motivation von Threads. U6-3 Vergleich von Thread-Konzepten. Organisatorisches

> Übung Betriebssysteme Globalübung 3 Michel Steuwer Wintersemester 2012/13

Verteilte Systeme CS5001

Shared-Memory Programmiermodelle

Prozesszustände (1a)

Nebenläufigkeit und Kommunikation in Go

Musterlösung Prüfung WS 01/02

Monitore. Klicken bearbeiten

Transkript:

Wegweiser Das Erzeuger-/Verbraucher-Problem Semaphore Transaktionen Botschaften Betriebssysteme WS 2013, Threads 75

Beispiele Erzeuger-/Verbraucher-Probleme Betriebsmittelverwaltung Warten auf eine Eingabe (Terminal, Netz) Reduziert auf das Wesentliche Erzeuger-Thread endlicher Puffer Verbraucher-Thread Betriebssysteme WS 2013, Threads 76

Ein Implementierungsversuch void produce() { while(true) { Erzeuger Verbraucher void consume() { while(true) { item = produce_item(); item = remove_item(); enter_item(item); consume_item(item); Betriebssysteme WS 2013, Threads 77

Blockieren und Aufwecken von Threads Busy Waiting bei Erzeuger-/Verbraucher-Problemen sinnlos. Daher: sleep(queue) TCBTAB[AT].Zustand=blockiert //TCB des aktiven Thread queue.enter(tcbtab[at]) schedule wakeup(queue) TCBTAB[AT].Zustand=bereit switch_to(queue.take) Betriebssysteme WS 2013, Threads 78

Ein Implementierungsversuch int count = 0; void produce() { Erzeuger Verbraucher while(true) { item = produce_item(); if (count == N) sleep(prodq); enter_item(item); count++; if (count == 1) wakeup(consq); void consume() { while(true) { if (count == 0) sleep(consq); item = remove_item(); count--; if (count == N - 1) wakeup(prodq); consume_item(item); Betriebssysteme WS 2013, Threads 79

Ein Implementierungsversuch int count = 0; void produce() { while(true) { Erzeuger item = produce_item(); if (count == N) sleep(prodq); enter_item(item); count++; if (count == 1) wakeup(consq); Verbraucher void consume() { while(true) { if (count == 0) sleep(consq); item = remove_item(); count--; if (count == N - 1) wakeup(prodq); consume_item(item); Betriebssysteme WS 2013, Threads 80

Wegweiser Das Erzeuger-/Verbraucher-Problem Semaphore Transaktionen Botschaften Betriebssysteme WS 2013, Threads 81

Semaphore class SemaphoreT { public: SemaphoreT(int howmany); //Konstruktor void down(); //P: passeren = betreten void up(); //V: verlaten = verlassen Betriebssysteme WS 2013, Threads 82

Kritischer Abschnitt mit Semaphoren SemaphoreT mutex(1); mutex.down(); do_critical_stuff(); //Kritischer Abschnitt mutex.up(); mutex.down(); do_critical_stuff(); //Kritischer Abschnitt mutex.up(); Ein Thread kann kritischen Abschnitt betreten Betriebssysteme WS 2013, Threads 83

Beschränkte Zahl SemaphoreT mutex(3); mutex.down(); do_critical_stuff(); //Kritischer Abschnitt mutex.up(); mutex.down(); do_critical_stuff(); //Kritischer Abschnitt mutex.up(); Drei Threads können kritischen Abschnitt betreten Betriebssysteme WS 2013, Threads 84

Auf dem Weg zu Erzeuger/Verbraucher SemaphoreT mutex(3); mutex.down(); enter_item(item) remove_item(item) mutex.up(); Maximal 3 item können in den Puffer Betriebssysteme WS 2013, Threads 85

Semaphor-Implementierung class SemaphoreT { int count; QueueT queue; public: SemaphoreT(int howmany); void down(); void up(); SemaphoreT::SemaphoreT( int howmany) { count = howmany; SemaphoreT::down() { if (count <= 0) sleep(queue); count--; SemaphoreT::up() { count++; if (queue.empty()) wakeup(queue); //Alle Methoden sind als //kritischer Abschnitt //zu implementieren Betriebssysteme WS 2013, Threads 86

Intuition (aber falsch) Erzeuger-Thread 3-Elemente Puffer Verbraucher-Thread SemaphoreT E_V(3); E_V.down(); enter_item(); remove_item(); E_V.up(); Betriebssysteme WS 2013, Threads 87

EV-Problem mit Semaphoren full mutex empty #define N 100 //Anzahl der Puffereinträge SemaphoreT mutex(1); //zum Schützen des KA SemaphoreT empty(n); //Anzahl der freien //Puffereinträge SemaphoreT full(0); //Anzahl der belegten //Puffereinträge Betriebssysteme WS 2013, Threads 88

EV-Problem mit Semaphoren void produce() { while (true) { Erzeuger Verbraucher void consume() { while (true) { item = produce_item(); enter_item(item); item = remove_item(); consume_item(item); Betriebssysteme WS 2013, Threads 89

EV-Problem mit Semaphoren void produce() { while (true) { Erzeuger Verbraucher void consume() { while (true) { item = produce_item(); empty.down(); enter_item(item); item = remove_item(); empty.up(); consume_item(item); Betriebssysteme WS 2013, Threads 90

EV-Problem mit Semaphoren void produce() { while (true) { Erzeuger Verbraucher void consume() { while (true) { item = produce_item(); empty.down(); enter_item(item); full.up(); full.down(); item = remove_item(); empty.up(); consume_item(item); Betriebssysteme WS 2013, Threads 91

EV-Problem mit Semaphoren void produce() { while (true) { Erzeuger Verbraucher void consume() { while (true) { item = produce_item(); empty.down(); mutex.down(); enter_item(item); mutex.up(); full.up(); full.down(); mutex.down(); item = remove_item(); mutex.up(); empty.up(); consume_item(item); Betriebssysteme WS 2013, Threads 92

Versehentlicher Tausch der Semaphor-Ops void produce() { while (true) { Erzeuger Verbraucher void consume() { while (true) { item = produce_item(); empty.down(); mutex.down(); enter_item(item); mutex.up(); full.up(); mutex.down(); full.down(); item = remove_item(); mutex.up(); empty.up(); consume_item(item); DEADLOCK Betriebssysteme WS 2013, Threads 93

Bedingungsvariablen Semaphore verbinden Zähler und Warteschlange Bedingungsvariablen stellen nur eine Warteschlange bereit Operationen: wait() und signal() Bedingung frei implementierbar Test der Bedingung muss mit Lock geschützt werden dieses Lock wird bei wait() atomar freigegeben und beim Aufwachen wieder gesperrt Betriebssysteme WS 2013, Threads 94

EV-Problem mit einem Monitor void produce() { Erzeuger Verbraucher void consume() { enter_item(); count++; remove_item(); count--; Betriebssysteme WS 2013, Threads 95

EV-Problem mit einem Monitor void produce() { lock(mutex); enter_item(); count++; unlock(mutex); Erzeuger Verbraucher void consume() { lock(mutex); remove_item(); count--; unlock(mutex); Betriebssysteme WS 2013, Threads 96

EV-Problem mit einem Monitor void produce() { lock(mutex); if (count == N) wait(not_full,mutex); enter_item(); count++; unlock(mutex); Erzeuger Verbraucher void consume() { lock(mutex); remove_item(); count--; if (count == N 1) signal(not_full); unlock(mutex); Betriebssysteme WS 2013, Threads 97

EV-Problem mit einem Monitor void produce() { lock(mutex); if (count == N) wait(not_full,mutex); enter_item(); count++; if (count == 1) signal(not_empty); unlock(mutex); Erzeuger Verbraucher void consume() { lock(mutex); if (count == 0) wait(not_empty,mutex); remove_item(); count--; if (count == N 1) signal(not_full); unlock(mutex); Betriebssysteme WS 2013, Threads 98

Monitore Sprachkonstrukt Datentyp der von mehreren Threads genutzte Daten und darauf definierte Operationen bereitstellt Operationen können kritische Abschnitte enthalten, welche unter gegenseitigem Ausschluss ablaufen Implementierung mittels Locks oder Bedingungsvariablen monitor MyMonitorT{ condition sync_queue;... void atomic_insert(x); void atomic_delete(x); void atomic_calc_sum(); Betriebssysteme WS 2013, Threads 99

Bei mehreren beteiligten Objekten Problem Jedes Konto als Monitor bzw. mit Semaphoren implementiert Konto2 nicht zugänglich/ verfügbar Abbruch nach 1. Teiloperation Abhilfe Alle an einer komplexen Operation beteiligten Objekte vorher sperren void ueberweisen( int Betrag, KontoT Konto1, KontoT Konto2) { Konto1.abbuchen(Betrag); Konto2.gutschrift(Betrag); Betriebssysteme WS 2013, Threads 100

Bei mehreren beteiligten Objekten Vorgehensweise beteiligte Objekte vor dem Zugriff sperren erst nach Abschluss der Gesamtoperation entsperren void ueberweisen( int Betrag, KontoT Konto1, KontoT Konto2) { lock(konto1); Konto1.abbuchen(Betrag); lock(konto2); if NOT (Konto2. gutschrift(betrag)) { Konto1.gutschrift(Betrag); unlock(konto1); unlock(konto2); Betriebssysteme WS 2013, Threads 101

Wegweiser Das Erzeuger-/Verbraucher-Problem Semaphore Transaktionen Botschaften Betriebssysteme WS 2013, Threads 102

Motivation Verallgemeinerung: Transaktionen Synchronisation komplexer Operationen mit mehreren beteiligten Objekten Rückgängigmachen von Teiloperationen gescheiterter komplexer Operationen Dauerhaftigkeit der Ergebnisse komplexer Operationen (auch bei Fehlern und Systemabstürzen) Voraussetzungen Transaktionsmanager: mehr dazu in der Datenbanken-Vorlesung alle beteiligten Objekte verfügen über bestimmte Operationen Betriebssysteme WS 2013, Threads 103

Konto-Beispiel mit Transaktionen void ueberweisung(int Betrag, KontoT Konto1, KontoT Konto2) { int Transaction_ID = begin_transaction(); use(transaction_id, Konto1); Konto1.abbuchen(Betrag); use(transaction_id, Konto2); if (Konto2.gutschreiben(Betrag)) { abort_transaction(transaction_id); //alle Operationen, die zur Transaktion gehören, //werden rückgängig gemacht commit_transaction(transaction_id); //alle Locks werden freigegeben Betriebssysteme WS 2013, Threads 104

Transaktionen: ACID Eigenschaften von Transaktionen Atomar: Komplexe Operationen werden ganz oder gar nicht durchgeführt. Konsistent (Consistent): Es werden konsistente Zustände in konsistente Zustände überführt, Zwischenzustände dürfen inkonsistent sein. Isoliert: Transaktionen dürfen parallel durchgeführt werden genau dann, wenn sichergestellt ist, dass das Ergebnis einer möglichen sequentiellen Ausführung der Transaktionen entspricht. Dauerhaft: Nach dem Commit einer Transaktion ist deren Wirkung verfügbar, auch über Systemabstürze hinweg. Betriebssysteme WS 2013, Threads 105

Nachteile von Semaphoren etc. Basieren auf der Existenz eines gemeinsamen Speichers Jedoch häufig Kommunikation zwischen Threads ohne gemeinsamen Speicher, z. B. Threads in unterschiedlichen Adressräumen Threads auf unterschiedlichen Rechnern massiv parallele Rechner: jeder Rechenknoten mit eigenem Speicher Betriebssysteme WS 2013, Threads 106

Wegweiser Das Erzeuger-/Verbraucher-Problem Semaphore Transaktionen Botschaften Betriebssysteme WS 2013, Threads 107

Synchrone Botschaften Senden int send(message, timeout, TID); synchron, d. h. terminiert, wenn das korrespondierende receive/wait durchgeführt wurde Ergebnis : false, falls das Timeout greift Warten int wait(message, timeout, &TID); akzeptiert eine Botschaft von irgendeinem Thread liefert die ID des Sender-Threads Empfangen int receive(message, timeout, TID); akzeptiert eine Botschaft von einem bestimmten Sender- Thread Betriebssysteme WS 2013, Threads 108

EV-Problem mit Botschaften Erzeuger Verbraucher void producer() { while (true) { void consumer() { item = produce_item(); send(item); while (true) { receive(item); consume_item(item); Betriebssysteme WS 2013, Threads 109

EV-Problem mit Botschaften Erzeuger void producer() { while (true) { item = produce_item(); receive(empty); send(item); Verbraucher void consumer() { while (true) { receive(item); send(empty); consume_item(item); Betriebssysteme WS 2013, Threads 110

EV-Problem mit Botschaften Erzeuger Verbraucher void producer() { while (true) { item = produce_item(); receive(empty); send(item); void consumer() { for(int i = 0; i < N; i++) send(empty); while (true) { receive(item); send(empty); consume_item(item); Betriebssysteme WS 2013, Threads 111

Wegweiser Zusammenspiel (Kommunikation) mehrerer Threads Einige typische Probleme Erzeuger / Verbraucher 5 Philosophen Leser/Schreiber Scheduling Betriebssysteme WS 2013, Threads 112

Dining Philosophers 5-Philosophen-Problem 5 Philosophen sitzen um einen Tisch, denken und essen Spaghetti zum Essen braucht jeder zwei Gabeln, es gibt aber insgesamt nur 5 Problem: kein Philosoph soll verhungern Betriebssysteme WS 2013, Threads 113

Die offensichtliche ( ) Lösung void Philosoph(int i) { Denken(); NimmGabel(i); NimmGabel((i+1)%5); Essen(); LegeZurückGabel(i); LegeZurückGabel((i+1)%5); Betriebssysteme WS 2013, Threads 114

Die offensichtliche (aber falsche) Lösung void Philosoph(int i) { Denken(); NimmGabel(i); NimmGabel((i+1)%5); Essen(); LegeZurückGabel(i); LegeZurückGabel((i+1)%5); Falsch kann zu Verklemmungen/Deadlocks führen (alle Philosophen nehmen gleichzeitig die linken Gabeln) zwei verbündete Phil. können einen dritten aushungern Betriebssysteme WS 2013, Threads 115

Leser/Schreiber-Problem Lesen und Schreiben von Daten (z. B. Datenbankeinträgen) mehrere Prozesse dürfen gleichzeitig lesen nur einer schreiben Betriebssysteme WS 2013, Threads 116

Scheduling Aufgabe: Entscheidung über Prozessorzuteilung an welchen Stellen (Zeitpunkte, Ereignisse,... ) nach welchem Verfahren Betriebssysteme WS 2013, Threads 117

Kriterien Scheduling Fairness: fairer Anteil an CPU für den Thread Effizienz: möglichst vollständige Auslastung der CPU Antwortzeiten: interaktiver Anwendungen Wartezeiten : von Hintergrundjobs Durchsatz: maximale Zahl von Aufgaben pro ZE Zusagen: ein Prozess muss spätestens dann fertig sein Energie Probleme Kriterien sind widersprüchlich Anwender-Threads sind in ihrem Verhalten oft unvorhersehbar Betriebssysteme WS 2013, Threads 118

Round Robin mit Zeitscheiben jeder Thread erhält reihum eine Zeitscheibe (time slice), die er zu Ende führen kann Wahl der Zeitscheibe zu kurz: CPU schaltet dauernd um zu lang: Antwortzeiten zu lang Betriebssysteme WS 2013, Threads 119

Prioritätssteuerung Threads erhalten ein Attribut: Priorität höhere Priorität verschafft Vorrang vor niederer Priorität Fragestellungen Zuweisung von Prioritäten Thread mit höherer Priorität als der rechnende wird bereit Umschaltung: sofort,...? ( preemptive scheduling ) häufig: Kombination Round Robin und Prioritäten Betriebssysteme WS 2013, Threads 120

Prioritätsumkehr (Priority Inversion) Beispielszenario: drei Threads X, Y, Z X höchste, Z niedrigste Priorität werden bereit in der Reihenfolge: Z, Y, X cobegin //X: {Sem.D();kurz;Sem.U(); //Y: {laaaaaaaaaaaaaaaang; //Z: {Sem.D();kurz;Sem.U(); coend Priorität Betriebssysteme WS 2013, Threads 121 Zeit

Prioritätsumkehr (Priority Inversion) Priorität cobegin //X: {Sem.D();kurz;Sem.U(); //Y: {laaaa... aaaaaaaang; //Z: {Sem.D();kurz;Sem.U(); coend Sem.D() laa a...ang Sem.D();k urzsem.u() Zeit P blockiert an Sem X wird bereit, verdrängt Y Y wird bereit, verdrängt Z X hat höchste Priorität, kann aber nicht laufen, weil es an von Z gehaltenem Semaphor blockiert und Y läuft und damit kann Z den Semaphor nicht freigeben. Betriebssysteme WS 2013, Threads 122

Zusammenfassung Threads Threads sind ein mächtiges Konzept zur Konstruktion von Systemen, die mit asynchronen Ereignissen und Parallelität umgehen sollen. Kooperierende parallele Threads müssen sorgfältig synchronisiert werden. Fehler dabei sind extrem schwer zu finden, da zeitabhängig. Bei der Implementierung von Synchronisationsprimitiven auf die Kriterien Sicherheit und Lebendigkeit achten. Durch Blockieren im Kern (z.b. mittels Semaphoren) kann Busy Waiting vermieden werden. Standardlösungen für typische Probleme, wie das Erzeuger/Verbraucher-Problem Betriebssysteme WS 2013, Threads 123