Reentrada y seguridad de hilos
A lo largo de la documentación, los términos reentrante y seguro para subprocesos se utilizan para marcar clases y funciones para indicar cómo se pueden utilizar en aplicaciones multihilo:
- Una función segura para subprocesos puede invocarse simultáneamente desde varios subprocesos, incluso cuando las invocaciones utilizan datos compartidos, ya que todas las referencias a los datos compartidos se serializan.
- Una función reentrante también puede invocarse simultáneamente desde varios subprocesos, pero sólo si cada invocación utiliza sus propios datos.
Por lo tanto, una función thread-safe es siempre reentrante, pero una función reentrante no es siempre thread-safe.
Por extensión, se dice que una clase es reentrante si sus funciones miembro pueden invocarse de forma segura desde múltiples hilos, siempre que cada hilo utilice una instancia diferente de la clase. La clase es thread-safe si sus funciones miembro pueden ser llamadas de forma segura desde múltiples hilos, incluso si todos los hilos utilizan la misma instancia de la clase.
Nota: Las clases Qt sólo se documentan como thread-safe si están pensadas para ser utilizadas por múltiples hilos. Si una función no está marcada como thread-safe o reentrant, no debería ser utilizada desde diferentes hilos. Si una clase no está marcada como segura para subprocesos o reentrante, no se debe acceder a una instancia específica de esa clase desde diferentes subprocesos.
Reentrada
Las clases C++ suelen ser reentrantes, simplemente porque sólo acceden a sus propios datos miembros. Cualquier hilo puede llamar a una función miembro en una instancia de una clase reentrante, siempre y cuando ningún otro hilo pueda llamar a una función miembro en la misma instancia de la clase al mismo tiempo. Por ejemplo, la clase Counter es reentrante:
class Counter { public: Counter() { n = 0; } void increment() { ++n; } void decrement() { --n; } int value() const { return n; } private: int n; };
La clase no es segura para hilos, porque si varios hilos intentan modificar el miembro de datos n, el resultado es indefinido. Esto se debe a que los operadores ++ y -- no siempre son atómicos. De hecho, normalmente se expanden a tres instrucciones de máquina:
- Cargar el valor de la variable en un registro.
- Aumentar o disminuir el valor del registro.
- Almacenar el valor del registro en la memoria principal.
Si el subproceso A y el subproceso B cargan el valor antiguo de la variable simultáneamente, incrementan su registro y lo almacenan de nuevo, acaban sobrescribiéndose el uno al otro, ¡y la variable sólo se incrementa una vez!
Seguridad de hilos
Claramente, el acceso debe ser serializado: El hilo A debe realizar los pasos 1, 2, 3 sin interrupción (atómicamente) antes de que el hilo B pueda realizar los mismos pasos; o viceversa. Una forma sencilla de hacer que la clase sea segura para los hilos es proteger todos los accesos a los miembros de datos con un QMutex:
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; };
La clase QMutexLocker bloquea automáticamente el mutex en su constructor y lo desbloquea cuando se invoca el destructor, al final de la función. Bloquear el mutex asegura que el acceso desde diferentes hilos será serializado. El miembro de datos mutex se declara con el calificador mutable porque necesitamos bloquear y desbloquear el mutex en value(), que es una función const.
Notas sobre las clases Qt
Muchas clases Qt son reentrantes, pero no son seguras para hilos, porque hacerlas seguras para hilos incurriría en la sobrecarga extra de bloquear y desbloquear repetidamente un QMutex. Por ejemplo, QString es reentrante pero no segura para hilos. Puedes acceder de forma segura a diferentes instancias de QString desde múltiples hilos simultáneamente, pero no puedes acceder de forma segura a la misma instancia de QString desde múltiples hilos simultáneamente (a menos que protejas los accesos tú mismo con un QMutex).
Algunas clases y funciones de Qt son thread-safe. Estas son principalmente las clases relacionadas con hilos (p.e. QMutex) y funciones fundamentales (p.e. QCoreApplication::postEvent()).
Nota: La terminología en el dominio multithreading no está totalmente estandarizada. POSIX utiliza definiciones de reentrante y thread-safe que son algo diferentes para sus APIs de C. Cuando utilices otras librerías de clases C++ orientadas a objetos con Qt, asegúrate de que se entienden las definiciones.
© 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.