Lösung - Universität Düsseldorf: Informatik

Werbung
Universität Düsseldorf
Mathematisch-naturwissenschaftliche Fakultät
Institut für Informatik
Prof. Dr. Michael Schöttner
Florian Klein
Kevin Beineke
Janine Haas
Lösungsvorschläge für die 2. Klausur zur Vorlesung
Informatik 1
im Wintersemester 2014/2015
am 30. März 2015
Bearbeitungszeit: 90 Minuten
Gesamtpunktezahl: 90 Punkte
Die vorliegende Klausur umfasst einschließlich Deckblatt 11 Blätter.
Bitte prüfen Sie die Vollständigkeit der Klausur, bevor Sie beginnen.
Beachten Sie bitte die Hinweise auf dem folgenden Blatt.
Name
Matrikelnummer
Aufgabe
1
2
3
4
5
6
7
8
9
max. Punktzahl
6
3
12
15
12
7
7
16
12
erreichte Punktzahl
Summe
Hinweise:
• Schalten Sie Ihr Mobiltelefon aus.
• Die Verwendung von Taschenrechnern ist nicht erlaubt.
• Verwenden Sie keinen Bleistift zum Schreiben.
• Schreiben Sie Ihre Antworten direkt auf die Aufgabenblätter.
• Tragen Sie auf jedem Blatt Ihre Matrikelnummer und Ihren Namen ein.
• Für Teilaufgaben wird keine negative Gesamtpunktzahl vergeben.
• Stichpunkte genügen als Antwort.
Viel Erfolg!
Matrikelnummer:
Aufgabe 1:
Name:
Zahlensysteme
6 Punkte
a) Wandeln Sie die Dezimalzahl 213 in eine Binärzahl um.
(1 Punkt)
(213)10
(1101 0101)2
b) Wandeln Sie die Binärzahl 1011 1001 1110 0011 in eine Hexadezimalzahl um.
(1011 1001 1110 0011)2
(1 Punkt)
(B9E3)16
c) Wandeln Sie die Hexadezimalzahl BA in eine Dezimalzahl um.
(BA)16
(1 Punkt)
(186)10
d) Wandeln Sie die Hexadezimalzahl CAFE in eine Binärzahl um.
(CAFE)16
(1 Punkt)
(1100 1010 1111 1110)2
e) Wandeln Sie die Binärzahl 0110 1000 in eine Dezimalzahl um.
(0110 1000)2
(1 Punkt)
(104)10
f) Wandeln Sie die Dezimalzahl 38 in eine Hexadezimalzahl um.
(38)10
(1 Punkt)
(26)16
Punkteverteilung: 1 Punkt für jede korrekte Umrechnung. Keine Teilpunkte.
Aufgabe 2:
Reguläre Ausdrücke
3 Punkte
a) Gegeben sei der folgende reguläre Ausdruck: R1 = (ab)∗ (ba)∗ ba
Markieren Sie für jedes der folgenden Wörter, ob es in der von R1 erzeugten Sprache
enthalten ist oder nicht.
Wort
ist enthalten
ab
(1,5 Punkte)
ist nicht enthalten
X
abba
X
baba
X
Punkteverteilung: 0,5 Punkte pro korrekter Markierung. 0 Punkte für falsche, doppelte oder fehlende Markierungen.
b) Gegeben sei der folgende reguläre Ausdruck: R2 = (00)∗ ((11)|(0))0
Markieren Sie für jedes der folgenden Wörter, ob es in der von R2 erzeugten Sprache
enthalten ist oder nicht.
3
(1,5 Punkte)
Matrikelnummer:
Name:
Wort
ist enthalten
0000
X
ist nicht enthalten
1101
X
111
X
Punkteverteilung: 0,5 Punkte pro korrekter Markierung. 0 Punkte für falsche, doppelte oder fehlende Markierungen.
4
Matrikelnummer:
Aufgabe 3:
Name:
Kontrollstrukturen
12 Punkte
a) Geben Sie für jedes der folgenden Codefragmente an, welchen Wert x und y am Ende haben.
1.
2.
int
int
for
x
y
}
x = −1;
y = 2;
( i n t i = 0 ; i < 4 ; i ++) {
+= y ;
∗= 2 ;
int
int
for
x
y
}
x = 7;
y = 3;
( i n t i = 5 ; i > 0 ; i −−) {
−= 1 ;
∗= x / 2 ;
i n t x = 16;
i n t y = 0;
while ( x > 0) {
x = x − (1 ∗ y ) ;
y += 4 ;
}
3.
int x =
int y =
do {
x = x
y = y
} while
4.
2;
2;
∗ (y − 1);
∗ −1;
( x < 10 | | y > 0 ) ;
x
29
y
32
x
2
y
36
x
-8
y
16
x
18
y
-2
(8 Punkte)
Punkteverteilung:
• Eine richtige Zahl gibt 1 Punkt.
• Eine falsche Zahl gibt 0 Punkte.
• Zwischenergebnisse geben keine Punkte.
b) Geben Sie an, was die folgende Funktion berechnet.
(2 Punkte)
public s t a t i c i n t func ( i n t [ ] array ) {
i n t a = 0 , b = 0 , c = 0;
for
if
if
if
}
( i n t i = 0; i
( array [ i ] %
( array [ i ] %
( array [ i ] %
<
6
6
6
a r r a y . l e n g t h ; i ++) {
== 0 ) a ++;
== 2 ) b ++;
== 4 ) c ++;
return a + b + c ;
}
Die Funktion berechnet die Anzahl der geraden Zahlen im Array.
Punkteverteilung:
• Es gibt 2 Punkte, wenn erkannt wurde, dass die Anzahl der geraden Zahlen im Array berechnet wird.
c) Der folgende Codeausschnitt soll den betraglich größten Wert des Arrays bestimmen und
ausgeben (in diesem Fall -9). Der Code enthält allerdings zwei Fehler. Finden Sie die Fehler
und erklären Sie diese.
5
(2 Punkte)
Matrikelnummer:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Name:
i n t a r r a y [ ] = new i n t [ ] { 1 , −2, 3 , 4 , 5 , −6, 7 , 8 , −9};
i n t max = 0 ;
f o r ( i n t i = a r r a y . l e n g t h − 1 ; i > 0 ; i −−) {
i f ( a r r a y [ i − 1 ] >= max ) {
max = a r r a y [ i − 1 ] ;
}
}
for ( int i =
int result
i f ( i ∗ −1
result =
}
}
0 ; i < a r r a y . l e n g t h ;++ i ) {
= max ;
>= max ) {
i;
System . o u t . p r i n t l n ( r e s u l t ) ;
Zeile 4/5/6 Das letzte Array-Element wird nicht betrachtet.
Zeile 12 Es wird nur der Index überprüft nicht das Array-Element an der Index-Stelle.
Zeile 18 Die Variable result ist unbekannt (Compiler-Fehler), da sie nur als Block-Variable innerhalb der forSchleife existiert.
Punkteverteilung:
• Ein gefundener Fehler gibt 0,5 Punkte.
• Die korrekte Beschreibung eines Fehlers gibt 0,5 Punkte.
6
Matrikelnummer:
Aufgabe 4:
Name:
Objekt-orientierter Entwurf
15 Punkte
In dieser Aufgabe sollen Sie Java-Klassen zur Verwaltung von Fahrzeugen für eine Autovermietung entwerfen.
Folgende Objekte und Eigenschaften sollen verwaltet werden:
• Unternehmen: hat einen Namen, mehrere Limousinen und mehrere Luxus-Limousinen.
Die Anzahl der Fahrzeuge soll beim Anlegen der Instanz festgelegt werden.
• Limousine: hat eine Nummer und einen Preis pro Kilometer.
• Luxus-Limousine: hat eine Nummer, einen Preis pro Kilometer und einen Chauffeur (Name genügt).
a) Definieren Sie für jedes Objekt in der obigen Liste eine Java-Klasse und setzen Sie diese sinnvoll
zueinander in Beziehung. Hinweis: Alle Instanzvariablen sollen außerhalb ihrer Klasse nicht
zugreifbar sein, auch nicht über Getter-und-Setter-Methoden!
(5 Punkte)
s i e h e Loesung zu b )
Punkteverteilung: to be written
b) Implementieren Sie für jede Klasse aus a) einen Konstruktor.
(5 Punkte)
p u b l i c c l a s s Limousine {
p r i v a t e i n t nummer ;
p r i v a t e double preis_pro_km ;
p u b l i c Limousine ( i n t n , double p ) {
nummer = n ;
preis_pro_km = p ;
}
}
p u b l i c c l a s s LuxusLimousine e x t e n d s Limousine
private String chauffeur ;
{
p u b l i c LuxusLimousine ( i n t n , double p , S t r i n g c ) {
super (n , p ) ;
chauffeur = c ;
}
}
p u b l i c c l a s s Unternehmen {
private String
name ;
p r i v a t e Limousine lim [ ] ;
p r i v a t e LuxusLimousine lux [ ] ;
p u b l i c Unternehmen ( S t r i n g n , L i m o u s i n e l [ ] , L u x u s L i m o u s i n e l x [ ] ) {
name = n ;
lim = l ;
lux = lx ;
}
}
Punkteverteilung: to be written
c) Schreiben Sie eine kurze Test-Klasse mit einer main-Methode, in der eine Instanz vom Typ
Unternehmen erzeugt und alle zugehörigen Variablen initialisiert werden. Für dieses Beispiel
soll das Unternehmen soll drei Limousinen und zwei Luxus-Limousine haben.
Hinweis: Für alle Instanzen reichen einfache Testdaten!
public c l a s s Test
{
p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] ) {
L u x u s L i m o u s i n e l x [ ] = { new L u x u s L i m o u s i n e ( 1 , 1 . 0 , " F r a n z " ) ,
new L u x u s L i m o u s i n e ( 2 , 1 . 2 , " B i r g i t " )
};
L i m o u s i n e l [ ] = { new L i m o u s i n e ( 5 , 0 . 5 ) ,
new L i m o u s i n e ( 6 , 0 . 4 5 ) ,
7
(5 Punkte)
Matrikelnummer:
Name:
new L i m o u s i n e ( 7 , 0 . 5 5 )
};
Unternehmen u = new Unternehmen ( " H e r t z " , l , l x ) ;
}
}
Punkteverteilung: to be written
8
Matrikelnummer:
Aufgabe 5:
Name:
Polymorphie
12 Punkte
Gegeben seien nachstehende Java-Klassen. Beachten Sie die Vererbungsbeziehungen, sowie die
Methoden aufhalten.
p u b l i c c l a s s Lebewesen { }
public class Tier
e x t e n d s Lebewesen { }
p u b l i c c l a s s Vogel e x t e n d s T i e r { }
public class Insekt extends Tier { }
public class Platz {
p u b l i c v o i d a u f h a l t e n ( Lebewesen l 1 , Lebewesen l 2 ) {
System . o u t . p r i n t l n ( " Lebewesen 1 und Lebewesen 2 an einem u n b e k a n n t e n P l a t z . " ) ;
}
}
p u b l i c c l a s s Wiese e x t e n d s P l a t z {
p u b l i c v o i d a u f h a l t e n ( Lebewesen l 1 , Lebewesen l 2 ) {
System . o u t . p r i n t l n ( " Lebewesen 1 und Lebewesen 2 a u f d e r Wiese . " ) ;
}
}
p u b l i c c l a s s Wald e x t e n d s P l a t z {
p u b l i c v o i d a u f h a l t e n ( Lebewesen l , Vogel v ) {
System . o u t . p r i n t l n ( " Lebewesen und Vogel im Wald . " ) ;
}
public void a u f h a l t e n ( Tier t ) {
System . o u t . p r i n t l n ( " E i n T i e r im Wald . " ) ;
}
}
Geben Sie für die nachstehenden Befehlssequenzen an, was jeweils auf der Konsole ausgegeben wird,
falls die Befehlssequenz fehlerfrei ist. Falls ein Fehler auftritt, beschreiben Sie diesen kurz.
Achtung: Die obigen Klassen beinhalten keine Fehler!
a) Befehlssequenz 1:
(3 Punkte)
Lebewesen l = new T i e r ( ) ;
Wald wald = new Wald ( ) ;
wald . a u f h a l t e n ( l , new Vogel ( ) ) ;
Ausgabe: Lebewesen und Vogel im Wald.
b) Befehlssequenz 2:
(3 Punkte)
Wiese w = new Wiese ( ) ;
P l a t z p = w;
p . a u f h a l t e n ( new Lebewesen ( ) , new Lebewesen ( ) ) ;
Ausgabe: Lebewesen 1 und Lebewesen auf der Wiese.
c) Befehlssequenz 3:
(3 Punkte)
Wiese w = n u l l ;
P l a t z p = w;
p . a u f h a l t e n ( new I n s e k t ( ) , new T i e r ( ) ) ;
Fehler: NullPointerException, da p = null
d) Befehlssequenz 4:
(3 Punkte)
9
Matrikelnummer:
Name:
Wald w = new Wald ( ) ;
P l a t z p = w;
p . a u f h a l t e n ( new Lebewesen ( ) , new Vogel ( ) ) ;
Ausgabe: Lebewesen1 und Lebewesen2 an einem unbekannten Platz.
Punkteverteilung:
• 1 Punkt falls erkannt wurde, dass ein Fehler vorliegt.
• 2 Punkte fuer die Begründung eines Fehlers.
• 3 Punkte fuer die richtige Ausgabe (falls kein Fehler vorliegt).
• 0 Punkte fuer eine falsche Ausgabe.
10
Matrikelnummer:
Aufgabe 6:
Name:
Hashing
7 Punkte
Gegeben ist eine Hash-Tabelle der Größe 11 und eine Liste mit den nachstehenden sieben Wörtern.
Die Hash-Werte für die Wörter sind schon bekannt und stehen neben dem jeweiligen Wort.
Wort
Hash-Wert
Katze
2
Tisch
5
Garten
10
Haus
5
Kind
10
Hund
4
Ball
2
Füllen Sie die Hash-Tabelle mit den Wörtern der Reihe nach. Verwenden Sie bei einer Kollision
jeweils die Sondierungsfunktion, die oberhalb der Tabelle als Java-Code angegeben ist.
public int s1(int hash) {
return (hash + 1) % 11;
}
public int s2(int hash) {
return (hash * hash) % 11;
}
Index
Eintrag
Index
0
Kind
0
1
Eintrag
1
Kind
2
Katze
2
Katze
3
Ball
3
Haus
4
Hund
4
Hund
5
Tisch
5
Tisch
6
Haus
6
7
7
8
8
9
9
Ball
10
Garten
10
Garten
Punkteverteilung:
11
Matrikelnummer:
Name:
• Jedes korrekt eingetragene Wort gibt 0,5 Punkte.
• Folgefehler geben keine Punkte.
12
Matrikelnummer:
Aufgabe 7:
Name:
Komplexität
7 Punkte
a) Die Algorithmen A1 bis A3 benötigen für ihre Ausführung si (i ∈ {1, . . . , 3}) Schritte. Die
Anzahl der Schritte si hängt dabei von der Größe n der Eingabe ab und sei gegeben durch:
(3 Punkte)
s1 = 3 log n + n
s2 = 2n + 8n + 3
s3 = 4n2 + 107.844n
Geben Sie für jeden Algorithmus die Zeitkomplexität mithilfe der O-Notation an.
Zeitkomplexität von A1 :
O(n)
Zeitkomplexität von A2 :
O(2n )
Zeitkomplexität von A3 :
O(n2 )
Punkteverteilung: 1 Punkt pro richtiger Antwort. Keine Teilpunkte.
b) Gegeben sei folgende Methode funk. Berechnen Sie die Komplexität des Algorithmus unter
Zuhilfenahme der O-Notation.
(2 Punkte)
p u b l i c s t a t i c long funk ( i n t n ) {
long ergebnis = 0;
i n t max ;
i f (1000 < n ) {
max = 1 0 0 0 ;
} else {
max = n ;
}
f o r ( i n t i = 0 ; i < n / 2 ; i ++) {
f o r ( i n t j = 1 ; j < max ; j ++) {
e r g e b n i s += i / j ;
}
}
return ergebnis ;
}
Zeitkomplexität:
Die äußere Schleife ist linear abhängig von n. Die innere Schleife ist durch die Konstante 1000 beschränkt.
⇒ O(n)
Punkteverteilung: 2 Punkte für die korrekte Angabe der Komplexität, Teilpunkte für die korrekte Laufzeitbestimmung einzelner Befehle.
c) Ermitteln Sie die Komplexitätsklasse des unten stehenden Algorithmus.
p u b l i c s t a t i c i n t b e r e c h n e ( i n t s t a r t W e r t , i n t add [ ] , i n t s u b [ ] ) {
i n t n = add . l e n g t h + s u b . l e n g t h ;
i n t i = 0;
w h i l e ( i < add . l e n g t h ) {
s t a r t W e r t += add [ i + + ] ;
}
i = 0;
while ( i < sub . l e n g t h ) {
s t a r t W e r t −= s u b [ i + + ] ;
}
return startWert ;
}
13
(2 Punkte)
Matrikelnummer:
Name:
Zeitkomplexität:
In der Methode berechne wird zweimal hintereinander über alle Elemente eines Arrays iteriert.
⇒ O(n)
Punkteverteilung: 2 Punkte für die korrekte Angabe der Komplexität, Teilpunkte für die korrekte Laufzeitbestimmung einzelner Befehle.
14
Matrikelnummer:
Aufgabe 8:
Name:
Binäre Suche und Binärbaum
16 Punkte
a) Führen Sie auf der folgenden Zahlenfolge eine binäre Suche nach der Zahl 8 durch. Geben Sie
bei jedem Suchschritt das Vergleichselement und seinen Index an.
(4 Punkte)
int array[] = {3, 7, 8, 12, 14, 17, 18, 20, 23}
0+8
c ⇒ Index = 4, V ergleichswert = 14
2
0+3
b
c ⇒ Index = 1, V ergleichswert = 7
2
2+3
c ⇒ Index = 2, V ergleichswert = 8
b
2
b
Punkteverteilung:
• Ein korrekter Index gibt 1 Punkt.
• Ein korrekter Vergleichswert gibt 0,5 Punkte.
• Die Angabe des Suchwertes gibt 0 Punkte.
• Die korrekte Anwendung des Prinzips gibt 1 Punkt.
b) Geben Sie einen ausgeglichenen binären Suchbaum mit den in Teil a) gegebenen Zahlen an.
(2 Punkte)
Punkteverteilung:
• Ein korrekter binärer Suchbaum gibt 2 Punkt.
• Ein nicht ausgeglichener Baum gibt 0 Punkte.
• Wenn es sich nicht um einen binären Suchbaum handelt gibt es 0 Punkte.
• Eine falsch angeordnete Zahl gibt einen Abzug von 1 Punkt.
• Eine fehlende Zahl gibt einen Abzug von 1 Punkt.
• Eine doppelte Zahl gibt einen Abzug von 0,5 Punkten.
c) Im Folgenden sind zwei Klassen gegeben, mit deren Hilfe ein binärer Suchbaum realisiert werden
kann.
public class Baum {
Knoten wurzel;
}
public class Knoten {
Knoten links;
Knoten rechts;
int wert;
}
15
(4 Punkte)
Matrikelnummer:
Name:
Schreiben Sie eine Methode
Knoten einfuegenRekursiv(Knoten wurzel, Knoten neu),
die ausgehend von der übergebenen Wurzel einen neuen Knoten in den binären Suchbaum einfügt.
Die Methode soll rekursiv arbeiten. Als Rückgabewert wird die aktuelle bzw. neue Wurzel erwartet.
Den Fall, dass ein Wert eingefügt werden soll, der im Baum schon existiert, können Sie ignorieren.
public Knoten einfuegenRekursiv(Knoten wurzel, Knoten neu) {
if (wurzel == null) {
wurzel = neu;
} else {
if (neu.wert < wurzel.wert) {
wurzel.links = einfuegenRekursiv(wurzel.links, neu);
}else{
wurzel.rechts = einfuegenRekursiv(wurzel.rechts, neu);
}
}
return wurzel;
}
Punkteverteilung:
• Das Testen von wurzel auf null gibt 1 Punkt.
• Eine korrekte Rekursionsaufruf bringt jeweils 1 Punkt.
• Die korrekte Rückgabe des Resultats gibt 1 Punkt.
• Ein Syntaxfehler führt zu einem Abzug von 1 Punkt.
• Ein Laufzeitfehler führt zu einem Abzug von 1 Punkt.
d) Schreiben Sie eine Methode
Knoten einfuegenIterativ(Knoten wurzel, Knoten neu),
die ebenfalls einen neuen Knoten in den binären Suchbaum einfügt, aber iterativ arbeitet.
public Knoten einfuegenIterativ(Knoten wurzel, Knoten neu) {
Knoten vater = null;
Knoten kind = null;
if (wurzel == null) {
wurzel = neu;
} else {
kind = wurzel;
while (kind != null) {
vater = kind;
if (neu.wert < kind.wert) {
kind = kind.links;
if (kind == null) {
vater.links = neu;
}
}else{
kind = kind.rechts;
if (kind == null) {
vater.rechts = neu;
}
}
}
}
16
(6 Punkte)
Matrikelnummer:
Name:
return wurzel;
}
Punkteverteilung:
• Das Testen von wurzel auf null gibt 1 Punkt.
• Eine korrekte Schleife bringt 2 Punkte.
• Das Testen des rechten Teilbaums gibt 1 Punkt.
• Das Testen des linken Teilbaums gibt 1 Punkt.
• Die korrekte Rückgabe des Resultats gibt 1 Punkt.
• Wenn der Knoten nicht eingefügt wird, werden 2 Punkte abgezogen.
• Ein Syntaxfehler führt zu einem Abzug von 1 Punkt.
• Ein Laufzeitfehler führt zu einem Abzug von 1 Punkt.
17
Matrikelnummer:
Aufgabe 9:
Name:
Nebenläufigkeit
12 Punkte
Eine neu gegründete Bank möchte es ihren Kunden ermöglichen, über Bankautomaten Geld einzuzahlen und abzuheben.
Um dies zu realisieren, muss ein Online-Banksystem aufgesetzt werden, in dem jeder Kunde ein globales Konto erhält.
Die untenstehende Klasse Konto besitzt als Attribute den aktuellen Kontostand und das Limit des Dispositionskredits,
sowie die zwei Methoden zum Ein- und Auszahlen. Einzahlung sollen beliebig möglich, Auszahlungen jedoch durch den
Dispositionskredit beschränkt sein. Das Banksystem ist so ausgelegt, dass jede Transaktion in einem eigenen Thread
verarbeitet wird. Dazu sind die Klassen AuszahlungsThread und EinzahlungsThread vorgesehen, die bei
jeder Instanzierung das Konto und den Betrag übergeben bekommen. Zur Vereinfachung wurde hier angenommen, dass
alle Konten lokal vorliegen und keine Kommunikation mit anderen Automaten oder Servern nötig ist.
p u b l i c c l a s s Konto {
p r i v a t e double kontostand = 0;
p r i v a t e double dispo = 0;
p u b l i c Konto ( d o u b l e k o n t o s t a n d ) {
t h i s . kontostand = kontostand ;
t h i s . dispo = 1000;
System . o u t . p r i n t l n ( " E r o e f f n e n e u e s Konto m i t " + k o n t o s t a n d + " Euro G u t h a b e n . " ) ;
}
public void einzahlen ( double betrag ) {
t h i s . k o n t o s t a n d += b e t r a g ;
System . o u t . p r i n t ( " E i n z a h l u n g von " + b e t r a g + " Euro . " ) ;
System . o u t . p r i n t l n ( " Neuer K o n t o s t a n d : " + t h i s . k o n t o s t a n d + " Euro . " ) ;
}
public void auszahlen ( double betrag ) {
t h i s . k o n t o s t a n d −= b e t r a g ;
System . o u t . p r i n t ( " A u s z a h l u n g von " + b e t r a g + " Euro . " ) ;
System . o u t . p r i n t l n ( " Neuer K o n t o s t a n d : " + t h i s . k o n t o s t a n d + " Euro . " ) ;
}
}
p u b l i c c l a s s EinzahlungsThread implements Runnable {
p r i v a t e Konto k o n t o ;
p r i v a t e double betrag ;
p u b l i c E i n z a h l u n g s T h r e a d ( Konto k o n t o , d o u b l e b e t r a g ) {
t h i s . konto = konto ;
this . betrag = betrag ;
}
p u b l i c void run ( ) {
konto . ei n z a hl e n ( b e t r a g ) ;
}
}
p u b l i c c l a s s AuszahlungsThread implements Runnable {
p r i v a t e Konto k o n t o ;
p r i v a t e double betrag ;
p u b l i c A u s z a h l u n g s T h r e a d ( Konto k o n t o , d o u b l e b e t r a g ) {
t h i s . konto = konto ;
this . betrag = betrag ;
}
p u b l i c void run ( ) {
konto . auszahlen ( b e t r a g ) ;
}
}
18
Matrikelnummer:
Name:
a) Analysieren Sie den angegebenen Ansatz mit Blick auf Semantik und Synchronisierung.
Erläutern Sie anschließend mögliche Probleme. Wie könnten die Probleme gelöst werden?
(6 Punkte)
Die Methoden auszahlen und einzahlen sind nicht synchronisiert. Dadurch kann ”Lost Update” auftreten,
wenn mehrere Threads die Methoden gleichzeitig aufrufen (auch untereinander, wenn z.B. zweimal einzahlen
aufgerufen wird). Ein weiteres Problem, das durch die fehlende Synchronisierung auftritt, ist, dass die Ausgaben
nicht unbedingt den letzten Stand nach der durchgeführten Transaktion ausgeben, sondern verzögert aufgerufen
werden können, nachdem weitere Ein- und Auszahlungen stattfanden. Darüberhinaus wird beim Auszahlen nicht
geprüft wird, ob das Guthaben ausreicht.
Lösung:
p u b l i c c l a s s Konto {
p r i v a t e double kontostand = 0;
p r i v a t e double dispo = 0;
p u b l i c Konto ( d o u b l e k o n t o s t a n d ) {
t h i s . kontostand = kontostand ;
t h i s . dispo = 1000;
System . o u t . p r i n t l n ( " E r o e f f n e n e u e s Konto m i t " + k o n t o s t a n d + " Euro G u t h a b e n . " ) ;
}
public synchronized void einzahlen ( double betrag ) {
t h i s . k o n t o s t a n d += b e t r a g ;
System . o u t . p r i n t ( " E i n z a h l u n g von " + b e t r a g + " Euro . " ) ;
System . o u t . p r i n t l n ( " Neuer K o n t o s t a n d : " + t h i s . k o n t o s t a n d + " Euro . " ) ;
}
public synchronized auszahlen ( double betrag ) {
i f ( t h i s . k o n t o s t a n d + t h i s . d i s p o >= b e t r a g ) {
t h i s . k o n t o s t a n d −= b e t r a g ;
System . o u t . p r i n t ( " A u s z a h l u n g von " + b e t r a g + " Euro . " ) ;
System . o u t . p r i n t l n ( " Neuer K o n t o s t a n d : " + t h i s . k o n t o s t a n d + " Euro . " ) ;
} else {
System . o u t . p r i n t l n ( " A u s z a h l u n g v e r w e i g e r t ! Konto n i c h t a u s r e i c h e n d g e d e c k t . " ) ;
}
}
}
Punkteverteilung:
• Fehlende Synchronisierung erkannt. (1 Punkt)
• Problematik durch fehlende Synchronisierung beschrieben (Punktabzug für unpräzise Antworten). (2 Punkte)
• Korrekte Lösung für die Synchronisierung angegeben (Punktabzug für unpräzise Antworten). (2 Punkte)
• Fehlende Guthaben-Bedingung erkannt und Lösung präsentiert. (1 Punkt)
b) Als vierte Klasse ist das Banksystem angegeben. In dieser Klasse wird ein Konto erstellt und
zwei Transaktionen durchgeführt. Unten finden Sie drei mögliche Ausgaben. Beschreiben Sie
jeweils, wie diese Ausgaben zustande kommen können.
p u b l i c c l a s s Banksystem {
p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] ) {
Konto k o n t o = new Konto ( 1 0 0 ) ;
new T h r e a d ( new E i n z a h l u n g s T h r e a d ( k o n t o , 2 0 ) ) . s t a r t ( ) ;
new T h r e a d ( new A u s z a h l u n g s T h r e a d ( k o n t o , 6 0 ) ) . s t a r t ( ) ;
}
}
Eroeffne neues Konto mit 100 Euro Guthaben.
1. Einzahlung von 20.0 Euro. Neuer Kontostand: 60.0 Euro
Auszahlung von 60.0 Euro. Neuer Kontostand: 60.0 Euro
19
(6 Punkte)
Matrikelnummer:
Name:
Eroeffne neues Konto mit 100 Euro Guthaben.
2. Auszahlung von 60.0 Euro. Neuer Kontostand: 60.0 Euro
Einzahlung von 20.0 Euro. Neuer Kontostand: 60.0 Euro
Eroeffne neues Konto mit 100 Euro Guthaben.
3. Auszahlung von 60.0 Euro. Neuer Kontostand: 40.0 Euro
Einzahlung von 20.0 Euro. Neuer Kontostand: 120.0 Euro
1. Vor der ersten Ausgabe wurden beide Ein- und Auszahlungen durchgeführt.
2. Thread 2 gibt vor Thread 1 aus. Vor den entsprechenden Ausgaben wurden bereits beide Ein- und Auszahlungen durchgeführt.
3. Hier tritt ”Lost Update” auf, sodass der Kontostand am Ende 120.0 Euro anstatt 60.0 Euro beträgt. Thread
1 liest 100.0 Euro und wird unterbrochen. Anschließend liest Thread 2 100.0 Euro, zieht 60.0 Euro ab und
gibt den Kontostand aus. Dann fährt Thread 1 fort, erhöht von 100.0 Euro (bereits zuvor gelesen) auf 120.0
Euro und gibt den Kontostand aus.
Punkteverteilung: Pro korrekter Beschreibung 2 Punkte. Teilpunkte möglich.
20
Herunterladen