Parallelität, Synchronisation

Slides:



Advertisements
Ähnliche Präsentationen
Object Relational Mapping
Advertisements

der Universität Oldenburg
der Universität Oldenburg
Transaktionsverwaltung Beispiel einer typischen Transaktion in einer Bankanwendung: 1.Lese den Kontostand von A in die Variable a: read(A,a); 2.Reduziere.
10.2 Wechselseitiger Ausschluss in Hardware
Wiederholung Betriebssystem bietet eine Abstraktion der Hardware an:
Beim Start eines Prozesses in Windows NT, 2000 wird a der Programmtext aus der exe-Datei ab der dort angegebenen Adresse gespeichert.
Folien 2-5, 7-8 © Prof. Dr. Manfred Rössle (FH Aalen)
C Tutorium – Semaphoren –
Progwerkstatt JAVA Klasse, Objekte, Konstruktoren, Methoden
Transaktionsverwaltung Beispiel einer typischen Transaktion in einer Bankanwendung: 1.Lese den Kontostand von A in die Variable a: read(A,a); 2.Reduziere.
Objektrelationales Mapping mit JPA Working with Persistent Objects Jonas Bandi Simon Martinelli.
Kapitel 7.2 Dining philosophers problem
Ausnahmen HS Merseburg (FH) WS 06/07.
Threads Richard Göbel.
Java: Objektorientierte Programmierung
Java: Dynamische Datentypen
Indirekte Adressierung
Java: Referenzen und Zeichenketten
Java: Grundlagen der Objektorientierung
Ein Beispiel in Java.
Klassenvariable. Da man für jede Kuh bzw. jede Henne auf dem Markt den gleichen Preis für ein Liter Milch, bzw. den gleichen Preis für ein Ei bekommt,
Polymorphie (Vielgestaltigkeit)
Objekte und Arbeitsspeicher
1 Vorlesung Informatik 2 Algorithmen und Datenstrukturen (02 – Funktionenklassen) Prof. Dr. Th. Ottmann.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (02 – Funktionenklassen) Tobias Lauer.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (02 – Funktionenklassen) Prof. Dr. Th. Ottmann.
PKJ 2005/1 Stefan Dissmann Ausblick Es fehlen noch: Möglichkeiten zum Strukturieren größerer Programme Umgang mit variabler Zahl von Elementen Umgang mit.
Zusammenfassung Vorwoche
Situationen Verteilte Anwendungen Wintersemester 06/07 © Wolfgang Schönfeld.
Datenbanksysteme für FÜ WS 2004/2005 Transaktionen 1 Worzyk FH Anhalt Transaktionen und Parallelverarbeitung Eigenschaften von Transaktionen Konsistenz.
Datenbanksysteme für FÜ SS 2000 Seite Worzyk FH Anhalt Transaktionen und Parallelverarbeitung Eigenschaften von Transaktionen Konsistenz Isolation.
DVG Klassen und Objekte
EDV Parallelprogrammierung1 Parallelprogrammierung mit JAVA.
1 Kapitel 12: Transaktionsverwaltung Oliver Vornberger Fachbereich Mathematik/Informatik Universität Osnabrück Osnabrück
1 Kapitel 12: Transaktionsverwaltung. 2 Transaktion Bündelung mehrerer Datenbankoperationen Mehrbenutzersynchronisation Recovery.
15.1 Synchronisation nebenläufiger Prozesse
Erhard Künzel für Info 9. Klasse: Digitale Schule Bayern© Erhard Künzel.
Einführung in die Programmierung Datensammlung
© 2005 Pohlig - Taulien Datenströme GK Informatik 1 Datenströme.
Einige Begriffe zum Anfang.... Transaktionsprozedur: Folge primitiver Operationen als Einheit der Konsistenz und der Robustheit. Transaktion (TA): Ausführung.
Ausführungsmodell Zustandsübergang einer Transaktion aus Nutzersicht:
Synchronisation paralleler Transaktionen AIFB SS Konzept der Transaktion 4.2 Konzept der Transaktion (1/4) Eine Transaktion ist ein in sich geschlossener,
Betriebliche Informationssysteme Prof. Dr. Michael Löwe
Seite 1 Interface - Konzept Ein Interface führt einen neuen Datentyp ein: interface Frau {... } Das Interface enthält Deklarationen ( keine Definitionen.
Entwicklung verteilter eingebetteter Systeme - Einführung
Programmierung paralleler Algorithmen mit MPI
Telecooperation/RBG Technische Universität Darmstadt Copyrighted material; for TUD student use only Grundlagen der Informatik I Thema 16: Ausnahmebehandlung.
WS 2012/13 Datenbanksysteme Mi 15:15 – 16:45 R Vorlesung #11 Transaktionsverwaltung.
WS 2011/12 Datenbanksysteme Mi 15:15 – 16:45 R Vorlesung #10 Transaktionsverwaltung.
Replikation und Synchronisation
Transaktion Huang Zhenhao FU Shuai.
Thread Synchronisation in JAVA
Learning By Doing Ausnahmebehandlung Exceptions (Ausnahmebehandlung) Typische Fehlverhalten zur Laufzeit: s. Buch S. 287ff -Verwendung von null-Objekten.
Learning By Doing Parallelverarbeitung Multithreading (Nebenläufigkeit) Alte Idee der Parallelverarbeitung statt rein sequentieller Prozesse Parallelverarbeitung.
Interprozess- kommunikation (IPC)
Parallelisierung für Multiprozessor-Maschinen
Transaktionen Dr. Heidrun Bethge Datenbanken II.
2. Kommunikation und Synchronisation von Prozessen 2
Transaktionsverwaltung
Prof. K. Gremminger Folie 1 Vorlesung Datenbanksysteme SS 2002 Abhängigkeiten zwischen Transaktionen (Fehlerklassen) u Lost-Update-Problem u Dirty Read.
Threads in Java Threads  Sprachumfang von Java Der Java-Standard fordert nur die Unterstützung von Thread-Prioritäten. Es gibt keine Forderung bzgl.:
6.3 Verteilte Transaktionen
Parallel Programming Semaphores / Reader - Writer - Lock
Transaktionsverwaltung Beispiel einer typischen Transaktion in einer Bankanwendung: 1.Lese den Kontostand von A in die Variable a: read(A,a); 2.Reduziere.
Effektives Delta Laden DOAG SID Data Warehouse. Ziele Welche CDC Methoden gibt es? Typische Fallen Verschiedene Lösungsansätze praktische Beispiele.
Transaktionsverwaltung Beispiel einer typischen Transaktion in einer Bankanwendung: 1.Lese den Kontostand von A in die Variable a: read(A,a); 2.Reduziere.
6.3 Verteilte Transaktionen
Der kritische Abschnitt
 Präsentation transkript:

Parallelität, Synchronisation Clemens Düpmeier, 28.03.2017

Übersicht Einführung und Grundbegriffe Java Threads Synchronisationskonzepte Kommunikation durch Nachrichtenaustausch Verklemmungen Semantik und Spezifikation nebenläufiger Prozesse In dieser Vorlesungseinheit geht es um Parallelität, ihre Erzeugung, Synchronisation von parallelen Abläufen, potentielle Probleme von Parallelität und ihre Bedeutung in Verteilten Anwendungen. Clemens Düpmeier, 28.03.2017

Einführung und Grundbegriffe Sequentielles System Rechner führt einen einzigen Strom von Anweisungen aus Paralleles System Anweisungen können gleichzeitig ausgeführt werden Beispiel: Mehrprozessor-Systeme, Rechnernetz Nebenläufiges System (concurrent system) Es existieren mehrere Ströme von Anweisungen, die unabhängig voneinander abgearbeitet werden Diese Ströme werden entweder parallel oder pseudoparallel ausgeführt Pseudoparallelität: Häufiger Wechsel zwischen Ausführungsströmen Clemens Düpmeier, 28.03.2017

Typische nebenläufige Systeme Betriebssysteme Prozesse laufen nebenläufig ab Verteilte Systeme Systeme, wie in der Vorlesung diskutiert Mehrere Prozesse auf (eventuell) verschiedenen Rechnern, die parallel zueinander ablaufen können Auch GUI Programme sind oft nebenläufig! GUI Programme arbeiten häufig mit Worker-Threads, die lang andauernde Aktionen nebenläufig zum zentralen GUI-Ergeignisbehandlungsthread durchführen Clemens Düpmeier, 28.03.2017

Prozess und Thread Prozess Ablauf eines Programms mit eigenen Ressourcen (z.B. Adressraum) Thread (paralleler) Ablaufvorgang innerhalb eines Prozesses Alle Threads in einem Prozess nutzen die gleichen Ressourcen (die vom Prozess) werden vom Benutzerprogramm verwaltet und erzeugt lightweight processes Bei der Modellierung von (parallelen) Vorgängen unterscheidet man meist nicht zwischen Prozess und Thread Clemens Düpmeier, 28.03.2017

Welche Problematiken gibt es bei Nebenläufigkeit? Clemens Düpmeier, 28.03.2017

Beispiel: The Dining Philosophers * Fünf Philosophen sitzen um einen runden Tisch. Jeder Philosoph beschäftigt sich entweder mit Denken oder mit Essen. In der Mitte steht eine große Schüssel mit Spaghetti. Ein Philosoph benötigt zwei Gabeln, um essen zu können. Zwischen jedem Teller liegt eine Gabel und ein Philosoph kann nur die Gabeln links und rechts von seinem Teller nehmen. *Dijkstra, 1968 Clemens Düpmeier, 28.03.2017

Was kann alles passieren? Ein Philosoph, der hungrig ist, muss so lange warten, bis die Gabeln rechts und links von ihm frei sind. Es kann passieren, dass ein Philosoph nie zum Essen kommt, auch wenn er hungrig ist. dieser Philosoph wird (im wahrsten Sinne des Wortes) ausgehungert man sagt: die Verteilung der Gabeln ist nicht fair Es kann auch passieren, dass alle Philosophen gleichzeitig hungrig sind und alle die Gabel an ihrer rechten Seite nehmen. dann kann kein Philosoph jemals essen das System befindet sich im Zustand der Verklemmung (Deadlock) Clemens Düpmeier, 28.03.2017

Beispielsituationen Deadlock Clemens Düpmeier, 28.03.2017

Begriffe zum Thema Synchronisation Synchronisation: Koordination nebenläufiger Prozesse regelt den Zugriff auf gemeinsame Ressourcen Verklemmung (Deadlock) Kein Prozess kann fortfahren, weil alle auf eine Bedingung warten, die nur ein anderer (ebenfalls wartender) Prozess erfüllen kann Aushungerung (Starvation) Ein Prozess wird dauerhaft nicht mehr zur Ausführung zugelassen, obwohl er noch nicht beendet ist Faire Zuteilung von Ressourcen Jedem wartendem Prozess wird eine Ressource irgendwann auch mal zugeteilt Clemens Düpmeier, 28.03.2017

Komplikationen durch Nebenläufigkeit Zusätzliche Sprachkonstrukte notwendig Zusätzlicher Aufwand für die Verwaltung der Nebenläufigkeit bei der Programmierung Nichtdeterminismus keine Annahmen über die Reihenfolge von Aktionen unterschiedlicher Prozesse zulässig Ergebnis eines Programms nicht mehr eindeutig vorhersehbar Fehlerfälle treten oft nur in ganz bestimmten Situationen auf siehe Beispiel der Verklemmung bei den Philosophen Dies macht den Entwurf, das Verständnis und den Test nebenläufiger Programme äußerst schwierig Clemens Düpmeier, 28.03.2017

Klassifizierung nebenläufiger Systeme Klassifizierung nach der Art der Interaktion zwischen Prozessen Interaktion durch Zugriff auf gemeinsame Ressourcen Interaktion durch Nachrichtenaustausch Beispiel: Viele Arbeiter arbeiten in einer Autowerkstatt Die Arbeiter benötigen manchmal Werkzeuge, die nur in beschränkten Maße vorhanden sind Wenn alle Exemplare eines Werkzeugs belegt sind, muss ein Arbeiter warten, der dieses Werkzeug benötigt In der Firma gibt es nur einen Meister, der Achsvermessungen durchführt Wenn ein Arbeiter für eine Autoreperatur eine Achsvermessung braucht, kommuniziert er mit dem Meister, der diese durchführt Clemens Düpmeier, 28.03.2017

Interaktion durch Zugriff auf gemeinsame Ressourcen Zugriff auf gemeinsame Variablen, Speicherbereiche Dieser Zugriff muss synchronisiert werden um die Ressource(n) in einem konsistenten Zustand zu halten um die Ressource(n) nach einer bestimmten Strategie (fair) auf auf die zugreifenden Prozesse zu verteilen Beispiel: abwechselndes Schreiben und Lesen Zuteilung von Druckaufträgen zu Druckern Klassische Synchronisationskonzepte hierfür sind: Semaphore Monitore (wird von Java direkt unterstützt), siehe später Clemens Düpmeier, 28.03.2017

Interaktion durch Nachrichtenaustausch Die Prozesse interagieren durch das Senden und Empfangen von Nachrichten (messages) synchronisierter Nachrichtenaustausch: der Sender wartet, bis der Empfänger empfangsbereit ist und die Nachricht vollständig empfangen und bearbeitet hat und gegebenenfalls ein Ergebnis zurückliefert asynchroner Nachrichtenaustausch: der Sender wartet nicht, bis der Empfänger empfangsbereit und/oder die Nachricht bearbeitet hat. Die Nachricht wird gegebenenfalls gepuffert Clemens Düpmeier, 28.03.2017

Typische Interaktionen bei Verteilten Systemen Zugriff auf gemeinsame Ressourcen RMI, CORBA, Servlet Container, etc. arbeiten implizit mit Thread-Pool Klassenvariablen von Entfernten Objekten, Servlets, etc. werden daher in der Regel gemeinsam von mehreren Threads genutzt Bei Zugriff auf Datenbanken ist eine Verbindung zur Datenbank eine evtl. gemeinsam genutzte Resource Zugriff über Nachrichtenaustausch typischer Weise bei Aufruf entfernter Methoden normaler Weise synchroner Aufruf, aber asynchrones Verhalten über Anwendungslogik realisierbar Clemens Düpmeier, 28.03.2017

Java Threads Wie erzeuge ich Nebenläufigkeit in Java Programmen (z.B. in Multithreaded Servern) Clemens Düpmeier, 28.03.2017

Java Threads Beim Start eines Java Programmes wird ein Prozess erzeugt, der u.a. einen Thread enthält, der die main-Methode der angegebenen Klasse ausführt Der Programmierer kann weitere Threads definieren und starten Ausführung von programmierten run() Methoden innerhalb von Thread Objekten 2 Möglichkeiten zur Definition der run() Methoden, die in einem Thread Objekt abgearbeitet werden Ableiten einer eigenen Klasse von Thread mit eigener run() Methode Implementieren des Interfaces Runnable durch eigene Klasse Clemens Düpmeier, 28.03.2017

Ableiten von der Klasse Thread public class myThread extends Thread { public void run() { System.out.println("Hello World"); } public static void main(String args[]) { MyThread t=new myThread(); t.start(); } } Thread Thread() Thread(String name // überschreiben! run() // startet Thread start() … Ein Thread Objekt ist ein Ablaufrahmen, innerhalb dem die run() Methode einer Klasse ausgeführt wird Der Ablauf wird mit dem Aufruf der start() Methode im Thread Objekt gestartet Clemens Düpmeier, 28.03.2017

Implementieren von Runnable Thread Thread(Runnable r) ... start() <<interface>> Runnable run() public class SomethingToRun implements Runnable { public void run() { System.out.println("Hello World"); } public static void main(String args[]) { SomethingToRun runner = new SomethingToRun(); Thread t=new Thread(runner); t.start(); } } Clemens Düpmeier, 28.03.2017

Beispiel: Klasse Loop1 Starten von 3 Threads public class Loop1 extends Thread { public Loop1(String name) { super(name); } public void run() { for (int i=1; i<=100; i++) System.out.println(getName() + "(" + i + ")"); } public static void main(String[] args) { Loop1 t1 = new Loop1("Thread 1"); Loop1 t2 = new Loop1("Thread 2"); Loop1 t3 = new Loop1("Thread 3"); t1.start(); t2.start(); t3.start(); } Starten von 3 Threads Clemens Düpmeier, 28.03.2017

Mögliche Ausgabe von Loop1 Thread 1(1) Thread 1(2) Thread 1(3) Thread 1(4) ... Thread 1(35) Thread 2(1) Thread 3(1) Thread 1(36) Thread 2(2) Thread 3(2) Thread 2(3) Thread 2(4) Thread 2(5) Thread 3(3) Thread 3(4) Thread 1(37) .... Die 3 Threads laufen zeitlich verzahnt ab die JVM schaltet zwischen den Threads um Keine Aussage über relative Geschwindigkeit der Threads möglich Wann zwischen 2 Threads umgeschaltet wird, ist nicht vorhersagbar Ausgabe des Programms nichtdeterministisch Clemens Düpmeier, 28.03.2017

Beispiel: Klasse Loop2 public class Loop1 extends Thread { public Loop1(String name) { super(name); } public void run() { for (int i=1; i<=10; i++) System.out.println(getName() + "(" + i + ")"); try { Thread.sleep(100); } catch (InterruptedException e) {} } public static void main(String[] args) { Loop1 t1 = new Loop1("Thread 1"); Loop1 t2 = new Loop1("Thread 2"); Loop1 t3 = new Loop1("Thread 3"); t1.start(); t2.start(); t3.start(); } sleep(long millis) lässt Thread 100 ms schlafen. Dies beeinflusst implizit die Threadreihenfolge, da schlafende Threads nicht bei Threadumschaltung berücksichtigt werden Man beachte, dass bei Operationen auf Threads (wie sleep()) die „InterruptedException“ abgefangen werden muss. Es kann nämlich äußere Einflüsse auf einen Thread geben, die dafür sorgen, dass eine Warteoperation eines Threads vorzeitig beendet wird. Dies wird über eine „InterruptedException“ dem Thread signalisiert! Clemens Düpmeier, 28.03.2017

Mögliche Ausgabe von Loop2 Thread 1(1) Thread 2(1) Thread 3(1) Thread 1(2) Thread 2(2) Thread 3(2) Thread 1(3) Thread 2(3) Thread 3(3) Thread 1(4) Thread 2(4) Thread 3(4) Thread 1(5) Thread 2(5) Thread 3(5) .... Die 3 Threads laufen scheinbar abwechselnd ab Auf diese Reihenfolge kann man sich allerdings nicht verlassen Um eine Reihenfolge zu erzwingen, sollte man auf alle Fälle andere, bessere Mechanismen verwenden siehe folgende Diskussion zu Synchronisationsmechanismen Clemens Düpmeier, 28.03.2017

Threads und Interrupts Ein „Interrupt“ ist eine Art Nachricht an einen Thread, seine augenblickliche Tätigkeit zu unterbrechen / abzubrechen Senden eines Interrupts Schicken eines Interrupts erfolgt durch Aufruf der Methode threadObject.interrupt() „Interrupt Flag“ wird gesetzt Empfangen eines Interrupts Bei Methodenaufrufen, die einen Thread blockieren (sleep(), join()), führt Interrupt zum Werfen einer InterruptedException Thread kann manuell das Erhalten eines Interrupts durch Aufruf der statischen Methode Thread.interrupted() abfragen Aufruf sollte in Methoden erfolgen, die längere Zeit arbeiten und nicht blockieren Clemens Düpmeier, 28.03.2017

Zugriff von Threads auf gemeinsame genutzte Objekte und Synchronisation solcher Zugriffe Clemens Düpmeier, 28.03.2017

Beispielszenario Mehrere Threads kooperieren durch Zugriff auf gemeinsam genutzte Objekte Beispiel: Klasse Konto mit einem Attribut Kontostand Klasse Bank, die ein Array von Konten enthält Bankangestellte, die Beträge auf Konten buchen, werden als Thread modelliert (Klasse Bankangestellter) Die Klasse Bankbetrieb enthält eine Bank und mehrere Bankangestellte, die auf dieses Objekt zugreifen Clemens Düpmeier, 28.03.2017

Beispiel: Klasse Konto und Klasse Bank public class Bank { private Konto[] konten; public Bank() { konten=new Konto[100]; for (int i=0; i < konten.length(); i++) konten[i]=new Konto(); } public void buchen(int kontonr, float betrag) { float alterStand=konten[kontonr].abfragen(); float neuerStand=alterStand + betrag; konten[kontonr].setzen(neuerStand); } public class Konto { private float kontostand; public void setzen(float betrag) { kontostand=betrag; } public float abfragen() { return kontostand; } } Clemens Düpmeier, 28.03.2017

Beispiel (Forts.): Klasse Bankangestellter public class BankAngestellter extends Thread { private Bank bank; public BankAngestellter(String name, Bank bank) { super(name); this.bank=bank; start(); } public void run() { for (int i=0; i < 10000; i++) { // Kontonnummer einlesen, simuliert durch Zufallszahl int kontonr=(int)(Math.random()*100); // Überweisung einlesen, simuliert durch Zufallszahl float betrag=(int)(Math.random()*1000)-500; bank.buchen(kontonr, betrag); } } Thread selbst startet die Ausführung der run() Methode Clemens Düpmeier, 28.03.2017

Beispiel (Forts.): Klasse Bankbetrieb public class BankBetrieb { public static void main(String[] args) { Bank sparkasse = new Bank(); BankAngestellter müller=new BankAngestellter("Peter Müller", sparkasse); BankAngestellter schmitt=new BankAngestellter("Petra Schmitt", sparkasse); } } Alle Angestellten greifen auf das gleiche Bankobjekt sparkasse zu Der Zugriff erfolgt parallel (Bankangestellte sind Threads) mit zufälligen Zahlungen Clemens Düpmeier, 28.03.2017

Was kann alles passieren? Der Thread "Peter Müller" will 100 EUR auf Konto Nr. 44 buchen Aufruf der Methode bank.buchen(44,100) Innerhalb dieser Methode wird die Methode abfragen() aufgerufen, die den Wert 50 zurückgibt Die Variable neuerStand wird auf 150 gesetzt Es wird auf den Thread "Petra Schmitt" umgeschaltet; Petra Schmitt will 20 EUR vom Konto Nr. 44 abbuchen Aufruf der Methode bank.buchen(44,-20) Innerhalb dieser Methode wird die Methode abrufen() aufgerufen, die den Wert 50 zurückliefert Die Variable neuer Stand wird auf 30 gesetzt Auf dem Kontoobjekt wird setzen(30) aufgerufen Es wird wieder auf den Thread "Peter Müller" umgeschaltet Die Ausführung der Methode bank.buchen(44,100) wird fortgesetzt; auf dem Kontoobjekt wird setzen(150) aufgerufen Clemens Düpmeier, 28.03.2017

Fazit In dem soeben beschriebenen Szenario ist das Abbuchen von 20 EUR "verloren gegangen" Dieser Effekt tritt zwar wahrscheinlich nur selten ein, das Programm ist jedoch fehlerhaft Weil der Effekt so selten eintrifft, sind solche Fehler vom Programmierer schwer zu finden Eine Reduzierung der Methode buchen() auf eine einzige Java Anweisung würde das Problem auch nicht lösen Eine Java Anweisung wird intern auf mehrere (z.B. Maschineninstruktionen) Anweisungen abgebildet Clemens Düpmeier, 28.03.2017

Weiterer Lösungsversuch public class Bank { private Konto[] konten; private boolean gesperrt; public Bank() { konten=new Konto[100]; for (int i=0; i < konten.length(); i++) konten[i]=new Konto(); gesperrt=false; } public void buchen(int kontonr, float betrag) { while (gesperrt) ; gesperrt=true; float alterStand=konten[kontonr].abfragen(); float neuerStand=alterStand + betrag; konten[kontonr].setzen(neuerStand); gesperrt=false; } Zu einem Zeitpunkt darf nur ein Bankangestellter die Methode buchen() ausführen Wir realisieren dies durch ein Sperrattribut gesperrt innerhalb der Bank Klasse Wie sieht es mit dieser Lösung aus? Clemens Düpmeier, 28.03.2017

Probleme mit neuer Lösung Die Parallelität wird unnötig eingeschränkt paralleles Buchen auf unterschiedlichen Konten ist unkritisch Schlechte Effizienz der Lösung Durch "aktives Warten" (busy waiting) wird unnötig Rechenzeit verschwendet Die Lösung ist falsch! Wenn die Variable gesperrt false ist, können mehrere Threads gleichzeitig die Anweisung "while(gesperrt)" passieren, bis die Variable auf true gesetzt ist - die Schleife ist nicht atomar! Clemens Düpmeier, 28.03.2017

synchronized Methoden und -Blöcke public class Bank { private Konto[] konten; public Bank() { konten=new Konto[100]; for (int i=0; i < konten.length(); i++) konten[i]=new Konto(); } public synchronized void buchen(int kontonr, float betrag) { float alterStand=konten[kontonr].abfragen(); float neuerStand=alterStand + betrag; konten[kontonr].setzen(neuerStand); } Clemens Düpmeier, 28.03.2017

Bedeutung von synchronized Jedes Objekt in Java besitzt eine Sperre Soll eine synchronized Methode ausgeführt werden, wird die Sperre gesetzt, wenn sie noch frei ist ist die Sperre bereits gesetzt, wird der aufrufende Thread blockiert der blockierte Thread wird beim Umschalten zwischen Threads nicht berücksichtigt (passives Warten) Nach Beendigung der synchronized Methode wird die Sperre wieder freigegeben Threads, die auf Freigabe der Sperre warten, werden dabei reaktiviert Lesen und Setzen der Sperre (falls frei) erfolgt als atomare Operation Also kann jeweils nur ein Thread die synchronized Methode ausführen liefert Lösung für Problem 2 und für Problem 3 Clemens Düpmeier, 28.03.2017

Zulassung von parallelen Buchungen public class Konto { private float kontostand; public synchronized void buchen(float betrag) { kontostand += betrag; } public float abfragen() { return kontostand; } } public class Bank { ... public void buchen(int kontonr, float betrag) { konten[kontonr].buchen(betrag); } } 1. Variante Methode buchen in Klasse Bank ohne synchronized synchronized-Methode buchen in Klasse Konto Clemens Düpmeier, 28.03.2017

2. Variante: synchronized Block public class Bank { private Konto[] konten; ... public void buchen(int kontonr, float betrag) { synchronized(konten[kontonr]) { float alterStand=konten[kontonr].abfragen(); float neuerStand=alterStand + betrag; konten[kontonr].setzen(neuerStand); } } } Parameter gibt Objekt an, auf das Sperre gesetzt werden muss, um in geschützten Bereich zu gelangen 2. Variante Verwendung eines synchronized Block von Code Objekt mit Sperre ist das konkrete Konto Sperre ist für ganzen Block gesetzt Clemens Düpmeier, 28.03.2017

synchronized Methoden und -Blöcke Folgende Codefragmente sind äquivalent class K { public synchronized void m() { ... } class K { public void m() { synchronized(this) { ... } Clemens Düpmeier, 28.03.2017

Aufruf von eigenen Methoden class K { public synchronized void m1() { m2(); } public synchronized void m2() { ... } public static void main(String[] args) { K kObject = new K(); kObject.m1(); // keine Blockade im obigen Aufruf Der aufrufende Thread blockiert sich nicht selbst Clemens Düpmeier, 28.03.2017

Wann synchronized verwenden? synchronize Statements kosten auch etwas Sperrmechanismus kostet Zeit! synchronize Statements können zu Verklemmungen führen Regel: Wenn von mehreren Threads auf ein Objekt oder eine Klassenvariable zugegriffen wird und mindestens einer der Threads den Objektzustand oder Variablenwert ändert, dann müssen alle Methoden, die auf den Zustand des Objektes oder den Wert der Variablen zugreifen, mit synchronized gekennzeichnet werden. Clemens Düpmeier, 28.03.2017

Alternativen Manchmal reicht das Schlüsselwort „volatile“ Das java.util.concurrent Package ab Java 1.5 enthält Klassen, die einfache atomare Variablen definieren verschiedene optimierte Lock-Klassen für spezielle Lock-Anwendungssituationen Höherwertige Datenstrukturen, die Thread-safe sind und intern mit optimierten Locks arbeiten Clemens Düpmeier, 28.03.2017

Wie wartet ein Thread auf einen anderen? Warten auf das Ende eines Threads Verwendung von t.join() [siehe nächste Folie] Warten auf eine Benachrichtung von einem (anderen) Thread Warten über wait() Methode von Object Benachrichtigen über notify() oder notifyAll() Clemens Düpmeier, 28.03.2017

Warten auf das Ende eines anderen Threads Wenn t ein Threadobjekt ist, wartet der Aufruf t.join() auf die Beendigung des Threads t Wartender Thread muss hierbei „InterruptedException“ abfangen while (t.isAlive()) { try { t.join(); } catch (InterruptedException ignored) { } } // After this loop, we know that t is dead Clemens Düpmeier, 28.03.2017

Benachrichtigung: Beispiel Warteschlange … synchronized (queue) { while (queue.isEmpty()) { try { queue.wait(); } catch (InterruptedException ignored) { } } elem=queue.removeFirst(); } ... Empfänger Sender … synchronized (queue) { queue.addLast(elem); queue.notify(); } … Ablauf Empfänger wartet darauf, dass eine bestimmte Bedingung an einem Objekt (in diesem Fall eine Warteschlange) eintritt (queue.wait()) Ein anderer signalisiert eine Änderung mit queue.notify() Achtung: Empfänger muss immer nach Aufwecken überprüfen, ob Bedingung auch tatsächlich gilt (Guarded Block Pattern) Clemens Düpmeier, 28.03.2017

Thread Pools Wie führe ich in einem Server parallel hereinkommende Anforderungen aus? Clemens Düpmeier, 28.03.2017

Warum Thread Pools? Server Applikationen müssen oft eine Vielzahl kurzer paralleler Aktionen auf Anforderung von Clients durchführen Bsp.: Web-Server, Datenbankserver, Mailserver, etc. Hierfür jedesmal einen neuen Thread zu erzeugen, hat eine Anzahl von Nachteilen Thread-Erzeugung selbst kostet Zeit Threads konsumieren Systemressourcen Zu viele gleichzeitige Threads könnnen zu Schwierigkeiten führen, z.B. bzgl. CPU oder Hauptspeicherauslastung Thread Pools bieten eine einfache Möglichkeit die Auslastung des Systems zu begrenzen Clemens Düpmeier, 28.03.2017

Einfache Implementierung eines Thread-Pools (1) public class WorkQueue { private final int nThreads; private final PoolWorker[] threads; private final LinkedList queue; public WorkQueue(int nThreads) { this.nThreads=nThreads; queue=new LinkedList(); threads = new PoolWorker[nThreads]; for (int i=0; i < nThreads; i++) { threads[i] = new PoolWorker(); threads[i].start(); } public void execute(Runnable r) { synchronized(queue) { queue.addLast); queue.notify(); } } Die Implementierung zeigt, wie missverständlich der Begriff Thread-Pool eigentlich ist. Als Benutzer erwartet man bei einem Thread-Pool eigentlich, dass man Methoden wie pool.getThread() bzw. pool.returnThread() hat, mit denen man sich als Anwender einen Thread besorgt, benutzt und dann wieder zurückgibt. Diese Implementierungsart hätte aber einige Probleme, wie z.B. das ein Benutzer vergisst, Threadobjekte zurückzugeben und mit der Zeit hat der Thread-Pool keine Objekte mehr. Daher nutzt unsere Poolimplementierung, wie gängige Threadpooimplementierungen ein anderes Konzept: Aktionen, die innerhalb eines Threads im Pool laufen sollen, werden im Threadpool in eine Arbeitswarteschlange gestellt, die dann von Threadobjekten im Pool abgearbeitet werden. Man beachte dabei, dass diese Arbeitswarteschlange ein Objekt ist, auf das alle Workerthreads zugreifen. Daher muss der Zugriff auf die Warteschlange synchronisiert sein. Clemens Düpmeier, 28.03.2017

Einfache Implementierung eines Thread-Pools (1) private class PoolWorker extends Thread { public void run() { Runnable r; while (true) { synchronized(queue) { while (queue.isEmptry()) { try { queue.wait(); } catch (InterruptedException ignored) { } } r=(Runnable)queue.removeFirst(); } // If we don‘t catch RuntimeException, the pool could leak threads try { r.run(); } catch (RuntimeException e) { // we should log error about failed run here! } } } } Die PoolWorker Threads arbeiten innerhalb einer Endlosschleife in der Arbeitswarteschlange befindliche Aufträge ab. Dabei kann es durchaus vorkommen, dass manchmal die Auftragswarteschlange leer ist. In diesem Fall muss der Thread warten, bis er wieder ein Arbeitsauftrag aquirieren kann. Diese Stelle im Code zeigt die typische Struktur eines „guarded block“, Clemens Düpmeier, 28.03.2017

Risiken bei der Nutzung von Thread-Pools Worker-Threads führen „Runnable“ Objekte parallel aus Zugriff auf Datenstrukturen, die von den Runnable Objekten gemeinsam genutzt werden Können zu Synchronisationsproblemen führen, wie wir bereits vorgestellt haben i.e. Zugriff muss evtl. synchronisiert werden Aufpassen, dass keine Deadlocks entstehen, wenn Runnable Objekte Ressourcen gegenseitig locken Threads aus dem Thread-Pool selbst können blockiert werden, wenn sich die run()-Methoden der Arbeitsobjekte „aufhängen“ Siehe Diskussion zu Servlets später! Clemens Düpmeier, 28.03.2017

Maßnahmen gegen solche Risiken Zugriff auf gemeinsam genutzte Datenstrukturen in den Task-Objekten sichern Insbesondere Klassenvariablen (falls alle Task Objekte von einer Klasse sind) Keine Tasks an Thread-Pools geben, die synchron auf Ergebnisse anderer Tasks warten => potentielle Deadlocksituation Vorsicht ist geboten, wenn Thread-Pools Tasks abarbeiten müssen, deren run() Methoden sehr lange laufen => sieht fast wie Deadlock aus z.B. bei falls sehr-langsame I/O-Vorgänge auftreten können Analyse der Tasks ist sehr wichtig Thread-Pool Größe sollte auf Last angepasst sein Evtl. macht es Sinn, mit mehreren getrennten Arbeitswarteschlangen und Pools zu arbeiten Statt eigener Implementierung eines Thread-Pools z.B. den ThreadPoolExecutor Service von java.util.concurrent verwenden Clemens Düpmeier, 28.03.2017

Wie groß sollte Größe des Pools sein? Nicht zu wenig, nicht zu viel = idealer Weise zwischen min, max Schranke Möglichst variabel, also anpassbar an Situation Für Tasks, die nur berechnender Natur sind, reicht ein Thread-Pool, der die Größe der Anzahl der Prozessoren (N) bzw. N+1 hat Für Tasks, die auf I/O-warten müssen, sollte die Poolgröße um einiges größer als die maximale Anzahl der möglichen parallelen Tasks sein, da manchmal Tasks im Wartezustand auf I/O längere Zeit festhängen können z.B. Web bei ultra-langsamen Clients ~ N*(1 + WT / ST), N Prozessoren, WT mittlere Wartezeit, ST mittlere Abarbeitungszeit = Anzahl, um alle Prozessoren im Mittel voll auszulasten Clemens Düpmeier, 28.03.2017

Transaktionen Clemens Düpmeier, 28.03.2017

Einführung Transaktionen lösen weitergehende Probleme beim Zugriff auf Daten (Resourcen) sowohl beim parallelen Zugriff als auch bei mehrerer Operationen auf Daten (Resourcen), die "zusammen" erfolgen müssen Es gibt mehrere Formen von Transaktionen Transaktionen als Bestandteil eines Datenbanksystems (Resourcesystems) Verteilte Transaktionssysteme für Transaktionen über Verteilte Resourcen Clemens Düpmeier, 28.03.2017

Motivation für Transaktionen (1) Customer Customer Neue Bestellung hinzugefügt Verkaufssumme bei Verkäufer unter „Total-Sales“ addiert Muss nun noch neue Bestellung in Bestelltabelle (Orders #) aufnehmen Problem: Letzte Aktion geht nicht, da z.B. Dateisystem voll C-no Order # Description Cost Order # Description Cost C-no Order # Description Cost 123 1000 400 Baseballs $2400 123 1000 400 Baseballs $2400 123 7000 250 Footballs $6500 SalesPerson SalesPerson Name Total-Sales Name Total-Sales Total-Sales Jones $3200 … … Jones $9700 … … $3200 … … Orders Orders Order # Order # 1000 … 1000 … 1000 … 2000 … 2000 … 2000 … 3000 … 3000 … 3000 … 4000 … 4000 … 4000 … 5000 … 5000 … 5000 … 6000 … 6000 … 6000 … FULL FULL FULL Clemens Düpmeier, 28.03.2017

Motivation für Transaktionen (2) Was passiert, wenn während der Ausführung des folgenden PL/SQL Programmcodes das Programm oder Betriebssystem abstürzt, z.B. durch Stromausfall, etc. … while c%found loop if v_gehalt > 10000 then update angestellter set gehalt = gehalt * proz1 where current of c; else update angestellter set gehalt = gehalt * proz2 end if; fetch c into v_gehalt; end loop; end; Clemens Düpmeier, 28.03.2017

Motivation Transaktionen (3) Was passiert, wenn nach Schritt 3 Programm, Datenbank oder Betriebssystem ausfällt, z.B. wegen Stromausfall, etc. Überweisung von 50 EUR von Konto A auf Konto B (1) Lese Kontostand von A in temporäre Variable a: read(A,a); (2) Reduziere den Kontostand um 50 EUR: a = a – 50; (3) Schreibe neuen Kontostand auf Konto A in Datenbank: write(A,a) (4) Lese den Kontostand von B in temporäre Variable b: read(B,b); (5) Erhöhe den Konstostand um 50 EUR: b = b + 50; (6) Schreibe neuen Kontostand von Konto B in Datenbank: write(B,b); Clemens Düpmeier, 28.03.2017

Begriff Transaktion (siehe auch Einführung) Eine Transaktion ist eine Folge von Daten(bank)operationen, die die Daten von einem logisch konsistenten Zustand in einen neuen konsistenten Zustand überführt und entweder ganz oder gar nicht ausgeführt wird (Man spricht auch von einer logischen Arbeitseinheit [Logical unit of work], die aus Sicht des Anwenders atomar ist) Im Fall unseres Kontobeispiels müssen bei der Kontobewegung immer beide Operationen zusammen (Abheben von A und Draufbuchen auf B) ganz oder gar nicht durchgeführt werden. Ansonsten „verliert“ man Geld. Clemens Düpmeier, 28.03.2017

Prinzipielles Schema für Transaktionskonzept Customer Customer C-no Order # Description Cost Order # Description Cost C-no Order # Description Cost Start Transaction Add Customer; Change Total-Sales of Sales person; Insert Order; If no errors then Commit Transaction; Else Rollback Transaction 123 1000 400 Baseballs $2400 123 1000 400 Baseballs $2400 123 7000 250 Footballs $6500 SalesPerson SalesPerson Name Total-Sales Name Total-Sales Total-Sales Jones $3200 … … Jones $9700 … … $3200 … … Orders Orders Order # Order # 1000 … 1000 … 1000 … 2000 … 2000 … 2000 … 3000 … 3000 … 3000 … 4000 … 4000 … 4000 … 5000 … 5000 … 5000 … 6000 … 6000 … 6000 … FULL FULL FULL Clemens Düpmeier, 28.03.2017

Transaktionen und SQL Relationale Datenbanken unterstützen das Transaktionskonzept über einen Transaktionsmanager, der über die folgenden SQL Anweisungen gesteuert werden kann START TRANSACTION ( Syntax: start transaction | begin [work] ) Kann explizit oder implizit formuliert sein und markiert den Start einer Transaktion COMMIT TRANSACTION ( Syntax: commit [work]; ) Eine Folge von Aktionen einer Transaktion wird als abgeschlossen markiert und dem Transaktionsmanager die Anweisung gegeben, die gesamte Folge dauerhaft zu speichern ROLLBACK TRANSACTION ( Syntax: rollback [work]; ) Die Transaktion wird explizit (durch Programm oder Person) oder implizit durch das System (auf Grund eines Fehlers oder einer Konsistenzverletzung) abgebrochen. Dabei werden alle Zustandänderungen im Rahmen der Transaktion wieder zurückgenommen (Rollback) Clemens Düpmeier, 28.03.2017

ACID-Eigenschaften von Transaktionen Atomicity: (Atomizität) Transaktionen werden entweder ganz oder gar nicht durchgeführt Consistency: (Konsistenz) Transaktionen überführe die Datenbank von einen konsistenten Zustand in einen neuen konsistenten Zustand Isolation: (Isolation) Nebenläufige (gleichzeitige) Transaktionen laufen jede für sich so ab, als würden sie alleine ablaufen Durability: (Dauerhaftigkeit) Die Wirkung einer Transaktion bleibt dauerhaft (auch bei einem Stromausfall) erhalten Clemens Düpmeier, 28.03.2017

ACID-Eigenschaften - A Atomicity (Atomizität) Transaktionen haben atomaren Charakter: Sie werden ganz oder gar nicht ausgeführt („Alles oder nichts“ Prinzip)  System muss sich merken, welche Aktionen im Rahmen einer Transaktion bereits durchgeführt wurden (Logging). Im Falle eines Fehlers müssen diese zurückgenommen werden (Rollback) Clemens Düpmeier, 28.03.2017

ACID-Eigenschaften - C Consistency (Konsistenz) Transaktionen bewahren die Konsistenz der Datenbank Sie überführen die Datenbank stets von einem konsistenten Zustand (bzgl. der Integritätsbedingungen) in den nächsten  Innerhalb einer Transaktion kann der Datenbankzustand temporär nicht-konsistent sein, z.B. eine Fremdschlüsselbedingung temporär verletzt sein Aber am Ende der Transaktion müssen alle Integritätsbedingungen erfüllt sein Clemens Düpmeier, 28.03.2017

ACID-Eigenschaften - I Isolation (Isolation) Transaktionen werden bei einem konkurrierenden Zugriff (Concurrency) auf die Datenbank logisch voneinander getrennt Jede Transaktion läuft in einem simulierten Einzelbenutzer-Zugriff ohne Beeinflussung der jeweils anderen Transaktion(en) ab  Wir werden noch sehen, dass dies nicht immer perfekt handhabbar ist Wesentliche Mechanismen für die Implementierung von Isolation sind Synchronisationsmechanismen, also Sperrmechanismen (Locks) beim Zugriff auf Daten sowie eine geeignete zeitliche Serialisierung der Aktionen (Scheduling) Clemens Düpmeier, 28.03.2017

ACID-Eigenschaften - D Durability (Dauerhaftigkeit) Erfolgreiche Datenbank-Updates im Rahmen von Transaktionen (Committed Transactions) bleiben dauerhaft erhalten Auch bei einem Stromausfall, Absturz der Datenbank, etc.  Durability und Atomicity gehen Hand in Hand – Können nicht die gesamten Aktionen einer Transaktion dauerhaft in der Datenbank gespeichert werden, wird die Datenbank auf den letzten konsistenten Zustand vor der Transaktion oder aber einen anderen Safepoint innerhalb der Transaktion zurückgesetzt Clemens Düpmeier, 28.03.2017

Beispiel für SQL-Transaktionen -- Transaktion T1 wird implizit geöffnet update Konto set balance = balance-50 where KontoID = 'A'; update Konto set balance = balance+50 where KontoID = 'B'; -- T1 wird beendet und die Ergebnisse in der DB festgeschrieben commit work; -- neue Transaktion T2 wird implizit geöffnet insert into Konto (KontoID, Name, balance) values ('C', 'Meyer', 0); Clemens Düpmeier, 28.03.2017

Transaktionssteuerung try { // AutoCommit ausschalten con.setAutoCommit(false); // DML-Anweisungen ... // COMMIT ausführen con.commit(); } catch (SQLException e) { // Änderungen zurücknehmen con.rollback(); } Methoden der Connection Klasse commit() rollback() Auto-Commit-Modus implizites Commit nach jeder Anweisung Transaktion besteht nur aus einer Anweisung Umschalten mittels setAutoCommit(boolean) Transaktionsisolationsebenen Setzen mittels setTransactionLevel(int) Abfragen mit getTransactionLevel() TRANSACTION_NONE TRANSACTION_READ_UNCOMMITTED TRANSACTION_READ_COMMITTED TRANSACTION_REPEATABLE_READ TRANSACTION_SERIALIZABLE Clemens Düpmeier, 28.03.2017

Problemarten zu Isolationsebenen (1) Keine Transaktion Probleme wie Verlieren von Updates, Inkonsistenzen der Daten, etc. möglich Bei parallelem Zugriff auf gleiche Daten sollten Transaktionen genutzt werden Dirty Read Innerhalb einer Transaktion werden Ergebnisse einer anderen gelesen, die noch nicht committed und daher evtl. nie in der Datenbank sind Leseoperationen benötigen keine Sperren Anwendung nur, wo Lesen solcher Daten nicht tragisch ist Clemens Düpmeier, 28.03.2017

Problemarten zu Isolationsebenen Nonrepeatable Read Innerhalb einer Transaktion werden Ergebnisse einer anderen gelesen, die bei einer zweiten Leseoperation innerhalb der gleichen Transaktion verschwunden sind (gelöscht) oder geändert wurden Falls die Konsistenz innerhalb der Transaktion von der Wiederholbarkeit abhängt, Nonrepeatable Reads blockieren Phantom Read Es wurde z.B. im Vorfeld des Auslesens einer Tabelle die Anzahl der Einträge in einer Tabelle ermittelt. Beim Auslesen der Tabelle gibt es auf einmal einen Eintrag, der vorher noch nicht da war (ein Phantom) Zur Verhinderung müssen Transaktinen komplett serialisiert werden Clemens Düpmeier, 28.03.2017

Isolationsebenen -  Isolationsebene Dirty Read Nonrepeatable Read Phantom Read Performance Read uncommitted möglich Sehr gut Read committed -  gut Repeatable read mittel serializable weniger gut Clemens Düpmeier, 28.03.2017

Concurrency, Isolation Probleme Beim konkurrierenden Zugriff (Concurrency) im Rahmen mehrerer Transaktionen auf gleiche Daten können verschiedene Probleme entstehen, für die Datenbanken Lösungen im Rahmen des Transaktionsbegriffes bieten müssen „Lost Update Problem“ „Dirty Read“ „Nonrepeatable Read“ „Phantom Read“ Clemens Düpmeier, 28.03.2017

Lost Update Problem Beispiel Flugbuchungssystem und Tabelle mit Feld, das Anzahl freier Sitzplätze im Flugzeug festhält Wenn die Aktionen der zwei Transaktionen T1 und T2 in gezeigter Weise zeitlich verschachtelt werden, wird 1 Sitzplatz doppelt vergeben Dies muss natürlich ein Transaktionskonzept verhindern! Clemens Düpmeier, 28.03.2017

Dirty Read – Nicht freigegebene Änderungen Wenn die Aktionen der zwei Transaktionen T1 und T2 in gezeigter Weise zeitlich verschachtelt werden, kann T2 evtl. den aktualisierten Sitzplatzwert der Transaktion T1 bereits „vor dem Commit“ lesen obwohl T1 danach diese Änderung per Rollback zurücknimmt Hier würde jetzt die Datenbank einen Sitzplatz als belegt markieren, dessen Buchung aber zurückgenommen wurde (d.h. der Sitz ist frei) Clemens Düpmeier, 28.03.2017

Nonrepeatable Read – nicht wiederholbares Lesen Innerhalb einer Transaktion T1 wird zweimal die Anzahl der Sitzplätze gelesen Eine zweite Transaktion ändert zwischen diesen beiden Leseoperationen die Anzahl freier Sitzplätze T1 liest damit innerhalb einer Transaktion zwei verschiedene Werte für die Anzahl der Sitzplätze. Clemens Düpmeier, 28.03.2017

Phantom Read – Lesen von Phantomen T1 zählt in der Variablen „count“ die Anzahl der Flüge, auf denen noch Plätze frei sind Eine zweite Transaktion T2 fügt jetzt in die Tabelle der Flüge einen neuen Flug hinzu, der eigentlich berücksichtigt werden müsste T1 ist aber schon beim Zählen an der Stelle der Tabelle vorbei, wo der neue Flug eingefügt wurde, und berücksichtigt daher diesen Flug nicht mehr Hätte T2 einen Flug gelöscht, der bereits gezählt worden wäre, wäre ein nicht länger existenter Eintrag (Phantom) bei der Zählung berücksichtigt worden Clemens Düpmeier, 28.03.2017

Transaktionen auf Ressourcen Transaktionen machen nicht nur für Datenbanksysteme Sinn Konzept anwendbar auf beliebige Systeme, die Ressourcen bereitstellen, die gemeinsam genutzt werden Und dabei modifiziert werden Verallgemeinerter Transaktionsbegriff für solche Ressource-Systeme Für Verteilte Systeme braucht man Verteilte Transaktionen Transaktionen über mehrere Ressource-Systeme hinweg Clemens Düpmeier, 28.03.2017

JTA-Transaction Beispielcode UserTransaction ut=context.getUserTransaction(); try { ut.begin(); updateServer1(); updateServer2(); ut.commit(); } catch (Exception e) { try { ut.rollback(); } catch (SystemException syex){ ... } } JTA = Java Transaction API API für Verteilte Transaktionen in Java über mehrere Ressource-Systeme hinweg Basiert auf Posix-Standard für Verteilte Transaktionen Implementierung wird über Ressource-Systeme bereitgestellt, die den Transaktionsmanager für JTA-Transaktionen implementieren Clemens Düpmeier, 28.03.2017