Hier habe ich eine Klasse, die zwei Threads hat, die Zugriff auf eine Liste haben. Ein Thread ersetzt die Liste regelmäßig durch eine aktualisierte Kopie und der andere Thread zeichnet den Inhalt der Liste auf dem Bildschirm.Muss ich den Zugriff auf eine Liste synchronisieren, die nur von einem Thread geändert wird?
public class ThreadSafePainter {
private List<String> dataList = new ArrayList<>();
/*
* starts a thread to periodically update the dataList
*/
public ThreadSafePainter() {
Thread thread = new Thread(() -> {
while (true) {
// replace out-dated list with the updated data
this.dataList = getUpdatedData();
// wait a few seconds before updating again
Thread.sleep(5000);
}
});
thread.start();
}
/*
* called 10 times/second from a separate paint thread
* Q: Does access to dataList need to be synchronized?
*/
public void onPaint(Graphics2D g) {
Point p = new Point(20, 20);
// iterate through the data and display it on-screen
for (String data : dataList) {
g.drawString(data, p.x, p.y);
p.translate(0, 20);
}
}
/*
* time consuming data retrieval
*/
private List<String> getUpdatedData() {
List<String> data = new ArrayList<>();
// retrieve external data and populate list
return data;
}
}
Meine Frage ist, muss ich den Zugriff auf die DataList synchronisieren? Wie soll ich das machen? Funktioniert das:
public ThreadSafePainter() {
...
synchronized (this) {
this.dataList = getUpdatedData();
}
...
}
public void onPaint(Graphics2D g) {
...
synchronized (this) {
for (String data : dataList)
...
}
}
Malen Sie den gesamten Bildschirm bei jeder Iteration neu? – StackFlowed
Da 'getUpdatedData()' jedes Mal eine neue Liste erstellt, benötigen Sie nur eine sichere Publikation. In diesem Fall wäre es ausreichend, das Feld "dataList" als "volatile" zu deklarieren. Es ist wichtig, dass dies funktioniert, wenn der Listenverweis gespeichert wird, nachdem er ausgefüllt wurde und nie wieder geändert wird (da das nächste Update eine neue Liste erstellt) und der Leser die Referenz einmal pro Verarbeitung liest (wie 'for (...: dataList) 'tut). Wenn es während einer 'Farbe' mehrmals auf die Liste zugreifen muss, muss es diese in einer lokalen Variablen speichern. – Holger
Immer wenn zwei oder mehr Threads einen ** mutable ** -Zustand teilen, muss ** eine Art Mechanismus zur Handhabung der Parallelität sein. Ob es sich um Low-Level-Synchronisation, höhere Parallelitätsklassen, "Atomic" -Klassen oder "flüchtige" Felder handelt, hängt von der tatsächlichen Situation ab, aber etwas muss immer an Ort und Stelle sein. – biziclop