Abstrakte Datentypen synchronisieren

BodyLAB

Bekanntes Mitglied
Hallo zusammen,

hab wieder eine Aufgabe zur Parallelität, dort soll man eine Queue schreiben die mit Threads ein Determiniertes Ergebnis liefert. Sprich es soll natürlich bei gleichen Startwerten immer das gleiche Ergebnis geliefert werden.
Wenn man die Queue nicht synchronisiert bekommt man irgendwann da Lesend und Schreiben drauf zugegriffen wird ein falsches Ergebnis.

So nun genug davon, nun dachte ich erst einmal an eine "simple" Lösung wie diese hier:
Java:
import java.util.LinkedList;

public class Queue<T> {
    private LinkedList<T> data;

    public Queue() {
        data = new LinkedList<T>();
    }

    synchronized public void enqueue(T object) {
        data.add(object);
    }

    synchronized public T dequeue() {
        if(data.isEmpty())
            return null;
        return data.removeFirst();
    }

}

Natürlich könnte man das ganze auch mit eine Inneren Klasse Node lösen etc. doch da habe ich eigentlich das selbe Problem bzw. die gleiche Frage wie ich bei dieser angegeben Lösung habe.

Nun sind ja nur die zwei Methoden enqueue und dequeue geschützt, da sämtliche Java Anweisungen nicht atomar sind somit unterbrechbar könnte doch data.add() oder data.removeFirst() unterbrochen werden. Hab ich hierbei ein Denkfehler oder stimmt das? Falls das stimmt wäre meine Idee nichts wert!

Nun habe ich etwas gesucht im Internet und das hier gefunden:
Java:
public class SynchronizedLinkedList<T> implements List<T> {

    private LinkedList<T> list;

    private Object lock;

    public void add(T object) {
        synchronized(lock) {
            list.add(object);
        }
    }

    // etc.
}

Beim zweiten hin sehen entsteht hierbei doch das selbe Problem.
Gibt es eine Möglichkeit eine ganze Klasse Synchronized zu erschaffen? So könnte man seine ganz eigene queue erstellen mit einer Node als InnerClass diese dann Synchronized machen und da die 2 Methoden synch. sind und die Klasse Node dann auch wäre das ganze Konstrukt nicht mehr unterbrechbar oder erneut ein Denkfehler?

Ich hoffe man verstehe was ich möchte. Bin gespannt wo mein Fehler ist ;-)
 

BodyLAB

Bekanntes Mitglied
Habe das hier noch gefunden um die LinkedList zu synchonisieren.

Java:
data = (LinkedList)Collections.synchronizedList(new LinkedList<T>());

somit hätte ich den Konstruktor von oben geändert zu:
Java:
public Queue() {
        data = (LinkedList<T>) Collections.synchronizedCollection(data);
    }

Wie aber könnte man das tun mit Innerer Klasse?
Java:
public class Queue<T> {
    
    public class Node<T> {
        ...
    }
    ...   
}
 

Blender3D

Top Contributor
So nun genug davon, nun dachte ich erst einmal an eine "simple" Lösung wie diese hier:
1) Das sind keine abstrakte Datentypen. Du meinst wohl generische Datentypen.
2) Ich glaube nicht, dass die Aufgabestellung darin besteht, einen bereits threadsicheren Container zu wrappen (kapseln). Eher ist deine Aufgabe eine Klasse Queue zu schreiben die threadsicher ist. Das bedeutet du sollst die Techniken, die du wahrscheinlich in den Vorlesungen hattest nutzen, um deine Queue threadsicher zu mache.
 

BodyLAB

Bekanntes Mitglied
2) Ich glaube nicht das die Aufgabestellung, ist einen bereits threadsicheren Container zu wrappen (kapseln). Eher ist deine Aufgabe eine Klasse Queue zu schreiben die threadsicher ist. Das bedeutet du sollst die Techniken, die du wahrscheinlich in den Vorlesungen hattest nutzen, um deine Queue threadsicher zu mache.
Genau das ist aber doch meine Frage!

Ich weiß nicht wie ich die Innere Klasse synchronisieren kann.
Wir hatten bis jetzt:
run - Methode,
synchronized - Methoden,
synchronized Blöcke und die
join - Methode

Mir erschließt gerade nicht so ganz wie ich mit diesen "Boardmitteln" das Problem gelöst bekomme.
Man könnte es ja so machen wie
Java:
static class SynchronizedCollection<E> implements Collection<E>, Serializable {
        @java.io.Serial
        private static final long serialVersionUID = 3053995032091335093L;

        @SuppressWarnings("serial") // Conditionally serializable
        final Collection<E> c;  // Backing Collection
        @SuppressWarnings("serial") // Conditionally serializable
        final Object mutex;     // Object on which to synchronize

        SynchronizedCollection(Collection<E> c) {
            this.c = Objects.requireNonNull(c);
            mutex = this;
        }

        SynchronizedCollection(Collection<E> c, Object mutex) {
            this.c = Objects.requireNonNull(c);
            this.mutex = Objects.requireNonNull(mutex);
        }

        public int size() {
            synchronized (mutex) {return c.size();}
        }
        public boolean isEmpty() {
            synchronized (mutex) {return c.isEmpty();}
        }
        public boolean contains(Object o) {
            synchronized (mutex) {return c.contains(o);}
        }
        public Object[] toArray() {
            synchronized (mutex) {return c.toArray();}
        }
        public <T> T[] toArray(T[] a) {
            synchronized (mutex) {return c.toArray(a);}
        }
        public <T> T[] toArray(IntFunction<T[]> f) {
            synchronized (mutex) {return c.toArray(f);}
        }

        public Iterator<E> iterator() {
            return c.iterator(); // Must be manually synched by user!
        }

        public boolean add(E e) {
            synchronized (mutex) {return c.add(e);}
        }
        public boolean remove(Object o) {
            synchronized (mutex) {return c.remove(o);}
        }

        public boolean containsAll(Collection<?> coll) {
            synchronized (mutex) {return c.containsAll(coll);}
        }
        public boolean addAll(Collection<? extends E> coll) {
            synchronized (mutex) {return c.addAll(coll);}
        }
        public boolean removeAll(Collection<?> coll) {
            synchronized (mutex) {return c.removeAll(coll);}
        }
        public boolean retainAll(Collection<?> coll) {
            synchronized (mutex) {return c.retainAll(coll);}
        }
        public void clear() {
            synchronized (mutex) {c.clear();}
        }
        public String toString() {
            synchronized (mutex) {return c.toString();}
        }
        // Override default methods in Collection
        @Override
        public void forEach(Consumer<? super E> consumer) {
            synchronized (mutex) {c.forEach(consumer);}
        }
        @Override
        public boolean removeIf(Predicate<? super E> filter) {
            synchronized (mutex) {return c.removeIf(filter);}
        }
        @Override
        public Spliterator<E> spliterator() {
            return c.spliterator(); // Must be manually synched by user!
        }
        @Override
        public Stream<E> stream() {
            return c.stream(); // Must be manually synched by user!
        }
        @Override
        public Stream<E> parallelStream() {
            return c.parallelStream(); // Must be manually synched by user!
        }
        @java.io.Serial
        private void writeObject(ObjectOutputStream s) throws IOException {
            synchronized (mutex) {s.defaultWriteObject();}
        }
    }

Doch ich vermute das ist hier nicht zielführend da so etwas doch die Parallelität sehr stark einschränkt.
Zur Not muss ich nächste Woche mal nachfragen ;-)

Vielleicht kann mir denn noch jemand helfen und erklären wie man das mit der Inneren Klasse lösen könnte ;-) Es reicht ja auch nur mal ein Keyword! Erst mal selber Denken ;-)

Das sind keine abstrakte Datentypen. Du meinst wohl generische Datentypen.
Ja generische Datentypen doch so gesehen sind das doch alles auch Abstrakte Datentypen. Wüsste ich wie ich eine Queue so gelöst bekomme, könnte man das Prinzip ja auch Listen, Bäume, Graphen, etc. übertragen. (oder ist das auch wieder ein Irrglauben, bei der Parallelität wie gesagt blicke ich noch nicht durch =()
 

Oneixee5

Top Contributor
Du schreibst oben: ...hab wieder eine Aufgabe zur Parallelität, dort soll man eine Queue schreiben
Was du machst: static class SynchronizedCollection<E> implements Collection<E>, Serializable {
Das passt doch nicht oder? public final class SynchronizedCollection<E> implements Queue<E> {. Ich sehe auch nicht, dass Serializable verlangt ist.
 

temi

Top Contributor
Du schreibst oben: ...hab wieder eine Aufgabe zur Parallelität, dort soll man eine Queue schreiben
Was du machst: static class SynchronizedCollection<E> implements Collection<E>, Serializable {
Das passt doch nicht oder? public final class SynchronizedCollection<E> implements Queue<E> {. Ich sehe auch nicht, dass Serializable verlangt ist.
Noch besser wäre wohl public final class SynchronizedQueue<E> implements Queue<E>
 

mrBrown

Super-Moderator
Mitarbeiter
Nun sind ja nur die zwei Methoden enqueue und dequeue geschützt, da sämtliche Java Anweisungen nicht atomar sind somit unterbrechbar könnte doch data.add() oder data.removeFirst() unterbrochen werden. Hab ich hierbei ein Denkfehler oder stimmt das?
Deine Idee ist vollkommen richtig.
add und renoveFirst werden innerhalb der synchronisierten Methode aufgerufen, dadurch kann jeweils nur ein Thread diese aufrufen. Dass die selbst intern nicht threadsicher sind, ist daher egal.
 

BodyLAB

Bekanntes Mitglied
@Oneixee5 und @temi hab mich da zu ungenau ausgedrückt
Oben steht man könnte es ja machen wie ... damit meinte ich dass ich mir dort nur die Implementierung der Klasse angeschaut habe um zu versuchen zu verstehen wie man das Problem lösen kann ;-) (Man muss ja nicht immer das Rad neu erfinden ;-))

@mrBrown wenn ich das jetzt aber nicht falsch verstehe könnte doch ein Thread wechsel statt finden in der LinkedList.
Hier mal ein Beispiel:
Java:
import java.util.LinkedList;


public class Queue<T> {
    private LinkedList<T> data;
    private int index = 0;

    public Queue() {
        data =  new LinkedList<T>();
    }

    synchronized public void enqueue(T object) {
        data.add(object);
        index++;
    }

    synchronized public T dequeue() {
        if(data.isEmpty())
            return null;
        return data.removeFirst();
    }

}

Was ich nicht verstehe ist, ein Thread betritt die synchronized Methode enqueue. Nun ist das Flag gesetzt das andere Threads diese Methode nicht betreten dürfen und warten müssen. Sobald aber der Aufruf data.add(object) erreicht ist springen wir doch in einen nicht synchronizeden Bereich und sind ab dort Unterbrechbar. Wenn nun ahhhh (jetzt wo ich es mir selbst aufschreibe habe ich es glaube verstanden =D) selbst wenn ein Thread wechsel statt findet, ist das Flag noch gesetzt. Das Betriebssystem wechselt fleißig alle Threads bis der Thread an der reihe ist der das Flag gesetzt hat. Danach beendet er seine Arbeit, geht aus der Methode und setzt das Flag auf bitte betreten =D

Stimmt das nun?

Entschuldigung für das viele durcheinander ;-)
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
I Abstrakte Datentypen - Liste Allgemeine Java-Themen 9
H Kombination Interface und Abstrakte Klasse bei Generics Allgemeine Java-Themen 3
P Abstrakte Klassen vs. Interface Allgemeine Java-Themen 4
S Klassen Abstrakte Klassen Allgemeine Java-Themen 5
C Abstrakte Klasse, lokale Variable-Problem Allgemeine Java-Themen 1
R Abstrakte Basisklasse und instanzierte Objekte der abgeleiteten Klasse als Basisklasse übergeben Allgemeine Java-Themen 2
F Abstrakte Klasse in "For each" Schleife Allgemeine Java-Themen 1
Z Abstrakte Klassen /Interface Allgemeine Java-Themen 5
C Abstrakte Klasse soll Methode aus Unterklasse aufrufen Allgemeine Java-Themen 3
J abstrakte Klassen, Konstanten und Konstruktor Allgemeine Java-Themen 9
S Wieso stehen in der API immer wieder abstrakte Methoden ? Allgemeine Java-Themen 7
P Abstrakte Elternklasse als Listener Allgemeine Java-Themen 6
L interface abstrakte klasse Allgemeine Java-Themen 21
I Interfaces und abstrakte Methoden Allgemeine Java-Themen 5
G Interface oder abstrakte Klasse Allgemeine Java-Themen 4
S Statische Methoden in abstrakte Klassen deklarieren? Allgemeine Java-Themen 17
G Abstrakte Fabrik für unterschiedliche Signaturen? Allgemeine Java-Themen 7
L Abstrakte Klasse: Member zwingend überschreibbar machen Allgemeine Java-Themen 2
MQue abstrakte Klasse Allgemeine Java-Themen 3
Q Schnittstelle/Abstrakte Klasse schreibt Annotation vor? Allgemeine Java-Themen 4
G Unterschied abstrakte Klasse und Interface? Allgemeine Java-Themen 3
S abstrakte klassen und packete Allgemeine Java-Themen 3
B Mit welchen Datentypen und Strukturierung am Besten dutzende Baccaratspiele Shcritt für Schritt durchsimulieren? Allgemeine Java-Themen 26
M Technische Realisierung von Atomic Datentypen Allgemeine Java-Themen 16
D JNA Speicherbelegung der Datentypen Allgemeine Java-Themen 13
H Mehrere Datentypen in einer Arraylist speichern Allgemeine Java-Themen 9
W Primitive Datentypen - Klassenpfad auflösen? Allgemeine Java-Themen 6
S Parametrisierte jUnit 5-Tests mit eigenen Datentypen/Klassen-Objekten als Test-Parameter Allgemeine Java-Themen 0
F Datentypen Kopieren von Datentypen Allgemeine Java-Themen 10
Asphorm Datentypen Datentypen werden nicht ordnungsgemäß umgewandelt Allgemeine Java-Themen 1
J Datentypen in Java Tabelle Allgemeine Java-Themen 2
B Chat auf andere Datentypen aufteilen Allgemeine Java-Themen 2
M ArrayList mit verschiedenen Datentypen in String konvertieren Allgemeine Java-Themen 10
C Best Practice [Arrays] Wie sinnvoll prüfen, ob Array primitive Datentypen enthält? Allgemeine Java-Themen 6
P Objekt mit verschiedenen Datentypen Allgemeine Java-Themen 5
H Datentypen Collection für SQL-Datentypen Allgemeine Java-Themen 2
M Java-Threads und Datentypen-Zugriffe Allgemeine Java-Themen 7
O primitive Datentypen threadsicher? Allgemeine Java-Themen 13
B Generische Datentypen MergeSort Allgemeine Java-Themen 5
B Sortieren mit generischen Datentypen Allgemeine Java-Themen 3
X Duplikate aus eigenen Datentypen entfernen Allgemeine Java-Themen 14
I Probleme mit Datentypen Allgemeine Java-Themen 4
D Addition generischer Datentypen Allgemeine Java-Themen 12
leifg Rechenoperationen auf generische Datentypen Allgemeine Java-Themen 10
M Generische Datentypen Allgemeine Java-Themen 14
C Primitive Datentypen in Threads Allgemeine Java-Themen 4
E Quelltext nach Datentypen durchsuchen Allgemeine Java-Themen 10
the[V]oid Primitive Datentypen Wrappen und als primitiv markieren? Allgemeine Java-Themen 7
B Eigene Datentypen Allgemeine Java-Themen 5
H Linksschieben << bei long-Datentypen Allgemeine Java-Themen 2
R Problem mit Datentypen Allgemeine Java-Themen 7
N Best Practice Kontakte synchronisieren Allgemeine Java-Themen 0
Nero90 DirectorySync - Verzeichnisse Synchronisieren Allgemeine Java-Themen 3
M Buffer-Vector einzeln und zusammen synchronisieren Allgemeine Java-Themen 4
S Synchronisieren von Dateien Allgemeine Java-Themen 3
P Buffer - Consumer Producer - Threads synchronisieren Allgemeine Java-Themen 15
Kr0e Synchronisieren: boolean,byte,char ? Allgemeine Java-Themen 2
S Objekt synchronisieren, sodass es nicht von mehreren Threads benutzt wird..? Allgemeine Java-Themen 2
G JTrees synchronisieren Allgemeine Java-Themen 7
M Javaprozess mit Batch-Script synchronisieren Allgemeine Java-Themen 2
N 2 Arrays koppeln (synchronisieren) Allgemeine Java-Themen 25
H Zugriff auf statische Variable synchronisieren Allgemeine Java-Themen 4
L Liste (SWT widget) mit HashSet synchronisieren Allgemeine Java-Themen 5
B Thread synchronisieren Allgemeine Java-Themen 2

Ähnliche Java Themen

Neue Themen


Oben