{{#index:kritischer Abschnitt|Abschnitt, kritisch|unkritischer Abschnitt|Abschnitt, unkritisch}} Im Quelltext aller Prozesse oder Threads lassen sich Abschnitte identifizieren, welche entweder kritisch, oder unkritisch im Hinblick auf Race Conditions sind.
Unter einem kritischen Abschnitt versteht man Programmteile, die während ihrer Ausführung auf der CPU nicht durch kritische Abschnitte anderer Prozesse oder Threads unterbrochen werden dürfen, sofern die beteiligten Prozesse oder Threads gemeinsam genutzte Betriebsmittel besitzen.
Unter einem unkritischen Abschnitt versteht man jeden Programmteil, der keinen kritischen Abschnitt darstellt.
Als Programmteil im Sinne der vorangegangenen Definitionen kann jeder Codeabschnitt mit der geforderten Eigenschaft gelten. Diese Programmteile lassen sich sowohl in einer Hochsprache wie Java, C, C++, Pascal, usw. identifizieren, als auch in Maschinencode oder Assembler.
Du musst dich daran erinnern, dass ein in einer Hochsprache wie Java, C, C++, Pascal, usw. angegebener Befehl in seiner Übersetzung in Maschinencode bzw. Assembler in mehrere kleine Befehle resultieren kann. Falls dir das entfallen war, so schau noch mal auf die Seite Vom_Quellcode_zum_Prozessor.
Ein Kontextwechsel findet immer zwischen zwei Maschinenbefehlen auf der CPU statt!
Das folgende Beispiel zeigt ein Java-Programm mit zwei Threads, bei deren Ausführung es zu Race Conditions kommt. Bei Thread_A werden durch spezielle Methoden kritische und unkritische Abschnitte gekennzeichnet.
public class Beispiel_Kritischer_Abschnitt {
static int counter = 0;
public static class Thread_A extends Thread {
public void run() {
do_something();
count_from_10();
do_something_else();
}
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();
}
}
Wo finden sich bei Thread_B kritische bzw. unkritische Abschnitte?
Werden Thread_A und Thread_B nebenläufig ausgeführt, so kann praktisch jederzeit ein Kontextwechsel erfolgen.
Angenommen Thread_B befindet sich innerhalb seines kritischen Abschnitts, und es erfolgt der Kontextwechsel zu Thread_A:
Die Synchronisations-Aufgabe besteht nur darin sicherzustellen, dass sich immer nur ein Prozess oder Thread zur Zeit in seinem kritischen Abschnitt befindet.
Dazu werden auf den folgenden Seiten mehrere Konzepte vorgestellt.
Bei dem hier gezeigten Java-Beispielcode konkurrieren jeweils zwei Threads um das gemeinsame Betriebsmittel einer einfachen Integer-Variablen.
Du musst verstehen, dass dies nur ein sehr einfaches Beispiel ist, und dass speziell bei Threads und "selbstgeschaffenen" Betriebsmitteln (wie der Integer-Variablen) der Programmierer selbst in der Pflicht zur Synchronisation ist. (Java bietet dafür das Schlüsselwort synchronized.)
Es gibt - neben der durch den Programmierer selbst geschaffenen Variablen - noch viele andere Betriebsmittel.
Durch die Beantwortung der letzten Frage ist damit klar:
Das Betriebssystem für die Synchronisation von Prozessen und Threads zuständig, welche auf gemeinsam genutzte Betriebsmittel zugreifen wollen.
Erinnert sei in diesem Zusammenhang an Systemaufrufe.
Warum wird hier an Systemaufrufe erinnert? Erläutere den Zusammenhang mit Betriebsmitteln und der Synchronisation von Prozessen und Threads!
Im Rahmen dieser Aufgabe existieren zwei Prozesse A und B, welche sich auf der CPU abwechseln.
Prozess A benötigt als Betriebsmittel das DVD-Laufwerk, es lassen sich also (ein oder mehrere) kritische Abschnitte in Prozess A identifizieren, in denen der Zugriff auf das genannte Betriebsmittel erfolgt.
Prozess B benötigt als Betriebsmittel eine bestimmte Datei auf der Festplatte, in die hineingeschrieben wird. Auch dafür lassen sich (ein oder mehrere) kritische Abschnitte identifizieren.
Weitere Betriebsmittel werden von den Prozessen nicht benötigt.
Angenommen Prozess B wird auf der CPU ausgeführt und befindet sich mitten in der Abarbeitung eines kritischen Abschnitts. Es erfolgt der Kontextwechsel zu Prozess A. Dieser arbeitet zunächst einen unkritischen Abschnitt ab, möchte dann aber einen kritischen Abschnitt betreten.
Begründe deine Entscheidung!
Diese Seite steht unter der Creative Commons Namensnennung 3.0 Unported Lizenz http://i.creativecommons.org/l/by/3.0/80x15.png