Seite 1 von 1

[gelöst] Ist QList.size() Thread-Safe?

Verfasst: 25. September 2010 14:41
von Zorki
Hallo zusammen,

ich verarbeite ein paar Daten von der Festplatte nach dem Producer-Consumer-Pattern und einer zwischengeschalteten QQueue.
Für das Einfügen und Extrahieren von Elementen nehme ich einen Mutex, allerdings wollte ich wissen,
ob ich das für einfache Abfragen - im konkreten Fall queue.size() - auch brauche.

Viele Grüße
Zorki

Verfasst: 25. September 2010 15:58
von franzf
Die Doku beantwortet deine Frage. Such ganz oben diesen Hinweis:
Note: All functions in this class are reentrant.
Auf das reentrant kann man klicken, dann gibts Info dazu.

Verfasst: 25. September 2010 16:14
von Zorki
... Hab ich wohl überlesen.
Allerdings verstehe ich noch nicht ganz, wieso ich Probleme haben sollte size() zu benutzen, da ja kein Speicher verändert sondern nur gelesen wird.
So wie ich das sehe könnte es höchstens passieren, dass ich keine ganz aktuelle Größenangabe bekomme.

Verfasst: 25. September 2010 16:21
von franzf
Zorki hat geschrieben:So wie ich das sehe könnte es höchstens passieren, dass ich keine ganz aktuelle Größenangabe bekomme.
Und dieses "höchstens" kann verdammt große Probleme hervorrufen. Wenn deine Liste schrumpft, nachdem du size() aufgerufen hast, und dann auf einen ungültigen Index zugreifst. Oder bei einer Iteration über alle Elemente zur Auswertung das letzte Element nicht mehr mit einbeziehst? Das sin schon gewaltige Probleme, die mit unter dein Programm crashen lassen.

Verfasst: 27. September 2010 11:28
von RHBaum
Und dieses "höchstens" kann verdammt große Probleme hervorrufen. Wenn deine Liste schrumpft, nachdem du size() aufgerufen hast, und dann auf einen ungültigen Index zugreifst. Oder bei einer Iteration über alle Elemente zur Auswertung das letzte Element nicht mehr mit einbeziehst? Das sin schon gewaltige Probleme, die mit unter dein Programm crashen lassen.
Eigentlich sind dies keine Probleme im Zusammenhang mit multithreaded funktionen, weil er eben in dem geschilderten Fall sowieso auf diesen Fall expliziet reagieren muss.
Das heisst er muss im oben genannten Fall einen kompletten Block an Code in eine critical Section hängen, egal ob die Funktion nun reentrant iss oder nicht.

das reentrant hingegen erlaubt es, die Abfrage eben auch ohne (eigenen) Schutz zu machen. Man muss halt nur damit rechnen, dass man wenn die funktion zurueckkomt, das ergebniss schon "veraltet" sein kann.
Fuer Code der absolute aktualitaet vorraussetzt, sind also reentrante funktionen ohne eigenen Schutz nichts. Aber sie sind halt gut geeignet um z.b. fortschritte zu melden, oder vorab anfragen, wo das ergebnis bei einer Direkten operation eh nochmal ueberprueft wird.

"Reentrant" garantiert Dir nichtmal das du ein Ergebniss erhaelst, was irgendwann mal aktuell war, es kann im Kollisionsfall selten auchmal "Müll" liefern. Aber es garantiert, das du durch die Abfrage das Object nicht durcheinanderbringst, in einen undefinierten zustand versetzt, so dass du eben selbst die möglichkeit hasst zu entscheiden, iss das ergebniss wichtig, dann brauch ich schutz, -> kostet performance, oder iss das ergebnis "unwichtig".

Ja es gibt auch (relativ) unwichtige Ergebnisse !
Fortschrittsbalken z.b.
oder useranzeigen, die sich mehrmals pro sekunde aktualisieren, da iss es ned sooo tragisch, wenn ab und an mal nen Ausrutscher bei ist.

@TE
wenn du MT programmierst, solltest Du dich wirklich mit den Begriffen:
atomar,
reentrant (in bezug auf funktionen/Methoden/operationen),
threadsafe (in Bezug auf Objecte/ganze Bibliotheken)
auskennen, vor allem was sie genau bedeuten. Falls man die falsch deutet, wird man so auf die Nase fallen ....
grad "threadsicher" wird sehr sehr gern falsch gedeutet :-), bzw auch von vielen falsch verwendet.

Ciao ...

Verfasst: 27. September 2010 17:04
von Zorki
Vielen Dank für die Antworten, ich weiß jetzt zumindest, woran ich bin.

In meinem Fall spielt das aber tatsächlich keine Rolle, da ich mit size() im Producerthread abfrage,
ob die maximale Puffergröße erreicht ist.
Da ich nur einen Producer haben kann der Wert also höchstens zu groß sein,
und mehr als mal unnötig warten kann folglich nicht passieren.