La prioridad de un hilo representa la importancia de ese hilo para el planificador. Pese a que el orden en que la CPU ejecuta un conjunto de hilos es indeterminado, el planificador tenderá a ejecutar el hilo con mayor prioridad de los que estén esperando. Sin embargo, no quiere decir que hilos con menos prioridad no se ejecutarán (es decir, no tendrá bloqueo de un hilo a causa de las prioridades). Simplemente, los hilos con menos prioridad tenderán a ejecutarse menos frecuentemente.
Se ha modificado MoreBasicThreads.cpp para mostrar los niveles
de prioridad. Las prioridades se ajustan utilizando la función
setPriority() de Thread
.
//: C11:SimplePriorities.cpp // Shows the use of thread priorities. //{L} ZThread #include <iostream> #include "zthread/Thread.h" using namespace ZThread; using namespace std; const double pi = 3.14159265358979323846; const double e = 2.7182818284590452354; class SimplePriorities : public Runnable { int countDown; volatile double d; // No optimization int id; public: SimplePriorities(int ident=0): countDown(5), id(ident) {} ~SimplePriorities() { cout << id << " completed" << endl; } friend ostream& operator<<(ostream& os, const SimplePriorities& sp) { return os << "#" << sp.id << " priority: " << Thread().getPriority() << " count: "<< sp.countDown; } void run() { while(true) { // An expensive, interruptable operation: for(int i = 1; i < 100000; i++) d = d + (pi + e) / double(i); cout << *this << endl; if(--countDown == 0) return; } } }; int main() { try { Thread high(new SimplePriorities); high.setPriority(High); for(int i = 0; i < 5; i++) { Thread low(new SimplePriorities(i)); low.setPriority(Low); } } catch(Synchronization_Exception& e) { cerr << e.what() << endl; } } ///:~
Listado 10.13. C11/SimplePriorities.cpp
En este ejemplo, el operador <<() se sobreescribe para mostrar el identificador, la prioridad y el valor de countDown de la tarea.
Puede ver que el nivel de prioridad del hilo es el más alto, y
que el resto de hilos tienen el nivel más bajo. No
utilizamos Executor
en este ejemplo
porque necesitamos acceder directamente al hilo para
configurar sus propiedades.
Dentro de SimplePriorities::run() se ejecutan 100,000 veces un costoso conjunto de cálculos en punto flotante. La variable d es volátil para intentar garantizar que ningún compilador hace optimizaciones. Sin este cálculo, no comprobará el efecto de la configuración de los niveles de prioridad. (Pruébelo: comente el bucle for que contiene los cálculos en doble precisión.) Con el cálculo puede ver que el planificador de hilos al hilo high se le da más preferencia. (Al menos, este fue el comportamiento sobre una máquina Windows). El cálculo tarda lo suficiente para que el mecanismo de planificación de hilos lo salte, cambie hilos y tome en cuenta las prioridades para que el hilo high tenga preferencia.
También, puede leer la prioridad de un hilo existente con getPriority() y cambiarla en cualquier momento (no sólo antes de que el hilo se ejecute, como en SimplePriorities.cpp) con setPriority().
La correspondencia de las prioridades con el sistema operativo es un problema. Por ejemplo, Windows 2000 tiene siete niveles de prioridades, mientras que Solaris de Sun tiene 231. El único enfoque portable es ceñirse a los niveles discretos de prioridad, como Low, Medium y High utilizados en la librería ZThread.