[gesichtete Version] | [gesichtete Version] |
Zeile 97: | Zeile 97: | ||
public class Wechseseitiger_Ausschluss_mit_Mutex { | public class Wechseseitiger_Ausschluss_mit_Mutex { | ||
Semaphor mutex | Semaphor mutex; | ||
static int counter = 0; | static int counter = 0; | ||
Zeile 113: | Zeile 113: | ||
private void count_from_10() { | private void count_from_10() { | ||
// Vorsicht: kritischer Abschnitt! | // Vorsicht: kritischer Abschnitt! | ||
P( mutex ); | |||
counter = 10; | counter = 10; | ||
counter++; | counter++; | ||
counter++; | counter++; | ||
System.out.println("A-Counter: " + counter); | System.out.println("A-Counter: " + counter); | ||
V( mutex ); | |||
} | } | ||
private void do_something_else() { | private void do_something_else() { | ||
Zeile 127: | Zeile 133: | ||
public void run() { | public void run() { | ||
System.out.println("Thread_B ist gestartet."); | System.out.println("Thread_B ist gestartet."); | ||
P( mutex ); | |||
counter = 20; | counter = 20; | ||
counter++; | counter++; | ||
Zeile 135: | Zeile 144: | ||
counter++; | counter++; | ||
System.out.println("B-Counter: " + counter); | System.out.println("B-Counter: " + counter); | ||
V( mutex ); | |||
} | } | ||
} | } | ||
public static void main(String[] args) { | public static void main(String[] args) { | ||
mutex = CreateSemaphor(1); | |||
Thread a = new Thread_A(); | Thread a = new Thread_A(); | ||
Thread b = new Thread_B(); | Thread b = new Thread_B(); |
Der folgende Quellcode ist bereits aus dem Kapitel Kritischer Abschnitt bekannt:
public class Beispiel_Kritischer_Abschnitt {
static int counter = 0;
public static class Thread_A extends Thread {
public void run() {
do_something(); // unkritisch
count_from_10(); // kritisch !!!
do_something_else(); // unkritisch
}
private void do_something() {
// unkritischer Abschnitt
System.out.println("Thread_A: unkritisch");
}
private void count_from_10() {
// Vorsicht: kritischer Abschnitt!
counter = 10;
counter++;
counter++;
System.out.println("A-Counter: " + counter);
}
private void do_something_else() {
// unkritischer Abschnitt
System.out.println("Thread_A: wieder unkritisch");
}
}
public static class Thread_B extends Thread {
public void run() {
System.out.println("Thread_B ist gestartet.");
counter = 20;
counter++;
counter++;
counter++;
counter++;
counter++;
counter++;
System.out.println("B-Counter: " + counter);
}
}
public static void main(String[] args) {
Thread a = new Thread_A();
Thread b = new Thread_B();
a.start();
b.start();
}
}
Zwei Threads A und B greifen jeweils auf die counter-Variable zu. Die counter-Variable stellt damit ein gemeinsam genutztes Betriebsmittel dar.
In beiden Threads lassen sich kritische Abschnitte identifizieren. Es muss dafür gesorgt werden, dass sich immer nur ein Thread zur Zeit in seinem kritischen Abschnitt befindet.
Dies nennt man den wechselseitigen Ausschluss: Wenn sich ein Thread in seinem kritischen Abschnitt befindet, dann muss ausgeschlossen sein, dass auch der andere Thread in seinen kritischen Abschnitt eintritt.
Du kennst bereits das aktive Warten (mit TSL), durch das ein wechselseitiger Ausschluss realisiert werden kann. Jedoch verschwendet das aktive Warten CPU-Zeit.
Ein Mutex kommt nun anstatt des aktiven Wartens zum Einsatz. Somit verschwindet auch der Nachteil der CPU-Zeitverschwendung.
Um einen Mutex in Listing 1 einzubauen, muss diese Datenstruktur zunächst erzeugt werden, um anschließend die P()- und V()-Operationen an den geeingneten Stellen aufzurufen.
public class Wechseseitiger_Ausschluss_mit_Mutex {
Semaphor mutex;
static int counter = 0;
public static class Thread_A extends Thread {
public void run() {
do_something(); // unkritisch
count_from_10(); // kritisch !!!
do_something_else(); // unkritisch
}
private void do_something() {
// unkritischer Abschnitt
System.out.println("Thread_A: unkritisch");
}
private void count_from_10() {
// Vorsicht: kritischer Abschnitt!
P( mutex );
counter = 10;
counter++;
counter++;
System.out.println("A-Counter: " + counter);
V( mutex );
}
private void do_something_else() {
// unkritischer Abschnitt
System.out.println("Thread_A: wieder unkritisch");
}
}
public static class Thread_B extends Thread {
public void run() {
System.out.println("Thread_B ist gestartet.");
P( mutex );
counter = 20;
counter++;
counter++;
counter++;
counter++;
counter++;
counter++;
System.out.println("B-Counter: " + counter);
V( mutex );
}
}
public static void main(String[] args) {
mutex = CreateSemaphor(1);
Thread a = new Thread_A();
Thread b = new Thread_B();
a.start();
b.start();
}
}
Möchte ein Prozess in seinen kritischen Abschnitt eintreten, so muss er zunächst die Funktion P(s) (bzw. down(s)) aufrufen. Hier wird geprüft, ob die Zählvariable des übergebenen Semaphors s noch einen Wert größergleich Eins (>=1) besitzt.
Am Ende der Bearbeitung eines kritischen Abschnitts muss der betreffende Prozess die Funktion V(s) (bzw. up(s)) aufrufen. Der Wert der Zählvariable des übergebenen Semaphors s wird um Eins erhöht, und falls sich in der Warteschlange des Semaphors ein (oder mehrere) Prozess(e) befinden, so entferne den ersten daraus und ändere seinen Zustand in bereit. Bei der nächsten Zuteilung der CPU kann dieser damit seinen kritischen Abschnitt betreten.
Diese Seite steht unter der Creative Commons Namensnennung 3.0 Unported Lizenz http://i.creativecommons.org/l/by/3.0/80x15.png