# Einelementiger Buffer - synchronized - swap



## peterlemon (14. Okt 2012)

Hallo,
ich habe hier eine Aufgabe, die ich nicht wirklich gelöst bekomme.
Wir haben einen wie folgt gegebenen einelementigen Puffer, der auf zwei Objekten synchronisiert ist:


```
public class Buffer1<T> {
private T content;
private boolean empty;
private Object r = new Object();
private Object w = new Object();

public Buffer1() {
empty = true;
}

public Buffer1(T content) {
this.content = content;
empty = false;
}

public T take() throws InterruptedException {
synchronized (r) {
while (empty) {
r.wait();
}
synchronized (w) {
empty = true;
w.notify();
return content;
}
}
}

public void put(T o) throws InterruptedException {
synchronized(w) {
while (!empty) {
w.wait();
}
synchronized (r) {
empty = false;
r.notify();
content = o;
}
}
}
public boolean isEmpty() {
return empty;
}
}
```

Nun soll eine Methode swap() hinzugefügt werden, die den Wert des Buffers mit einem anderen Wert tauscht. Falls der Buffer gerade leer ist, soll sie suspendieren.
Meine Überlegung war folgende:


```
public void swap(T o) throws InterruptedException {
synchronized(w) {
while (empty) {
w.wait();
}
synchronized (r) {
T buf = o;
o = content;
r.notify();
content = buf;
}
}
}
```

Nun kann es doch aber zu deadlocks kommen.. muss ich ein drittes Lock einführen, um das Problem zu lösen?
Oder sollte ich die ganze Methode swap() auf synchronized sezten?


----------



## SlaterB (15. Okt 2012)

vertracktes Konstrukt durchaus,
mit nur einem synchronised überall, nur einem Monitor, gäbe es keinen Deadlock, aber warum dann bisher so kompliziert gebaut?
das scheint doch extra so gemacht, dann kaum zu streichen erlaubt? ..

warum ist swap() nicht andersum, wie take() aufgebaut?
dann sollte es meiner Ansicht nach klappen, put() ist erlaubt, ein take gleichzeitig verhindet,
verhält sich selber wie take() freilich ohne es am Ende leer zu lassen, w muss nicht informiert werden,
r.notify(); bleibt drin,

dabei auch schon einen Deadlock getestet? mein Kopf schwirrt bei sowas ein wenig, 
bisher glaube ich aber noch dass besser dran als andersrum, wo ich den Deadlock mit take() sehe:
beide gehen bei 'empty' einen Schritt weiter, haben aber unterschiedlichen Monitor und warten jeweils auf den anderen


----------



## Marco13 (15. Okt 2012)

Ja, ist kompliziert. Das, was dort nachgebaut werden soll, erinnert vom Ziel her an ReentrantReadWriteLock (Java 2 Platform SE 5.0) - vermutlich wäre es damit sehr leicht. Wenn man sich aber mal die Implementierung dieser Klasse ansieht, versinkt man schnell in Demut. Wenn's darum ginge: Vor alle Methoden ein dickes "synchronized" wäre zwar vermutlich "sicher", aber nicht sinnvoll. Wie grundlegend darf die Klasse denn geändert werden?


----------

