Reentranz und Thread-Sicherheit
In der gesamten Dokumentation werden die Begriffe „reentrant“ und „thread-safe“ verwendet, um Klassen und Funktionen zu kennzeichnen und anzugeben, wie sie in Multithread-Anwendungen eingesetzt werden können:
- Eine threadsichere Funktion kann gleichzeitig von mehreren Threads aufgerufen werden, selbst wenn die Aufrufe gemeinsam genutzte Daten verwenden, da alle Verweise auf die gemeinsam genutzten Daten serialisiert werden.
- Eine reentrante Funktion kann ebenfalls gleichzeitig von mehreren Threads aufgerufen werden, jedoch nur, wenn jeder Aufruf eigene Daten verwendet.
Daher ist eine threadsichere Funktion immer reentrant, eine reentrante Funktion ist jedoch nicht immer threadsicher.
Im weiteren Sinne gilt eine Klasse als reentrant, wenn ihre Mitgliedsfunktionen sicher von mehreren Threads aufgerufen werden können, solange jeder Thread eine andere Instanz der Klasse verwendet. Die Klasse ist threadsicher, wenn ihre Mitgliedsfunktionen sicher von mehreren Threads aufgerufen werden können, selbst wenn alle Threads dieselbe Instanz der Klasse verwenden.
Hinweis: Qt-Klassen werden nur dann als threadsicher dokumentiert, wenn sie für die Verwendung durch mehrere Threads vorgesehen sind. Wenn eine Funktion nicht als threadsicher oder reentrant gekennzeichnet ist, sollte sie nicht von verschiedenen Threads aus verwendet werden. Ist eine Klasse nicht als threadsicher oder reentrant gekennzeichnet, sollte von verschiedenen Threads aus nicht auf eine bestimmte Instanz dieser Klasse zugegriffen werden.
Reentrancy
C++-Klassen sind oft reentrant, einfach weil sie nur auf ihre eigenen Mitgliedsdaten zugreifen. Jeder Thread kann eine Mitgliedsfunktion einer Instanz einer reentranten Klasse aufrufen, solange kein anderer Thread gleichzeitig eine Mitgliedsfunktion derselben Instanz der Klasse aufrufen kann. Beispielsweise ist die folgende Klasse „ Counter “ reentrant:
class Counter
{
public:
Counter() { n = 0; }
void increment() { ++n; }
void decrement() { --n; }
int value() const { return n; }
private:
int n;
};Die Klasse ist nicht threadsicher, denn wenn mehrere Threads versuchen, das Datenelement ` n` zu ändern, ist das Ergebnis undefiniert. Dies liegt daran, dass die Operatoren ` ++ ` und ` -- ` nicht immer atomar sind. Tatsächlich werden sie in der Regel in drei Maschinenbefehle expandiert:
- Laden des Werts der Variablen in ein Register.
- Den Wert des Registers erhöhen oder verringern.
- Den Wert des Registers wieder im Hauptspeicher speichern.
Wenn Thread A und Thread B gleichzeitig den alten Wert der Variablen laden, ihren Registerwert inkrementieren und ihn wieder zurückschreiben, überschreiben sie sich gegenseitig, und die Variable wird nur einmal inkrementiert!
Thread-Sicherheit
Es ist offensichtlich, dass der Zugriff serialisiert werden muss: Thread A muss die Schritte 1, 2 und 3 ohne Unterbrechung (atomar) ausführen, bevor Thread B dieselben Schritte ausführen kann; oder umgekehrt. Eine einfache Möglichkeit, die Klasse threadsicher zu machen, besteht darin, den gesamten Zugriff auf die Datenelemente mit einem ` QMutex` zu schützen:
class Counter
{
public:
Counter() { n = 0; }
void increment() { QMutexLocker locker(&mutex); ++n; }
void decrement() { QMutexLocker locker(&mutex); --n; }
int value() const { QMutexLocker locker(&mutex); return n; }
private:
mutable QMutex mutex;
int n;
};Die Klasse „ QMutexLocker “ sperrt den Mutex automatisch in ihrem Konstruktor und entsperrt ihn, wenn der Destruktor am Ende der Funktion aufgerufen wird. Das Sperren des Mutex stellt sicher, dass der Zugriff aus verschiedenen Threads serialisiert wird. Das Datenelement „ mutex “ wird mit dem Qualifizierer „ mutable “ deklariert, da wir den Mutex in „ value() “ sperren und entsperren müssen, bei der es sich um eine „const“-Funktion handelt.
Hinweise zu Qt-Klassen
Viele Qt-Klassen sind reentrant, aber nicht threadsicher, da ihre Threadsicherheit einen zusätzlichen Overhead durch das wiederholte Sperren und Entsperren eines ` QMutex` verursachen würde. Beispielsweise ist ` QString ` reentrant, aber nicht threadsicher. Sie können sicher von mehreren Threads gleichzeitig auf verschiedene Instanzen von ` QString ` zugreifen, aber Sie können nicht sicher von mehreren Threads gleichzeitig auf dieselbe Instanz von ` QString ` zugreifen (es sei denn, Sie schützen die Zugriffe selbst mit einem ` QMutex`).
Einige Qt-Klassen und -Funktionen sind threadsicher. Dabei handelt es sich hauptsächlich um die Thread-bezogenen Klassen (z. B. ` QMutex`) und grundlegende Funktionen (z. B. ` QCoreApplication::postEvent()`).
Hinweis: Die Terminologie im Bereich Multithreading ist nicht vollständig standardisiert. POSIX verwendet für seine C-APIs Definitionen von „reentrant“ und „thread-safe“, die sich etwas unterscheiden. Wenn Sie andere objektorientierte C++-Klassenbibliotheken mit Qt verwenden, stellen Sie sicher, dass Sie die Definitionen verstehen.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.