CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament d’Arquitectura de Computadors
Sincronización de Threads en Java
(Seminaris de CASO)
Autors
Josep Joan Ribas Prats
Sergio Liminiana Bernat
Introducción
Los threads o hilos de ejecución son segmentos de código
de un programa que se ejecutan secuencialmente de modo
independiente de otras partes del programa.
 Un proceso puede estar constituido por uno o mas threads.
 Un thread esta compuesto por :

– Una CPU virtual
– El código que ejecuta el procesador
– Los datos sobre los que trabaja el código

Dos threads comparten código si ejecutan código de
objetos que pertenecen a la misma clase.
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
2
Introducción (II)

Los datos pueden ser o no compartidos por diferentes
threads. Eso ocurre cuando tienen acceso a un objeto
común.
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
3
Para qué?

Los threads se utilizan para aislar y coordinar tareas.

Sin el uso de threads hay aplicaciones que son casi
imposibles de programar:
• Las que tienen tiempos de espera importantes entre etapas
• Las que consumen muchos recursos de CPU e impiden que el procesador
atienda simultáneamente otros eventos o peticiones del usuario
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
4
Tipos.

Tipos de threads que pueden aparecer en una aplicación:
• Threads completamente independientes, que realizan tareas no
relacionadas. Éste es el caso más sencillo y no requiere ninguna
programación especial.
• Threads que trabajan en una misma tarea, pero sin interferir ni intercambiar
relación entre ellos. Por ejemplo, threads que colaboran en el producto de
dos matrices ocupándose cada una de ellas de calcular ciertas filas de la
matriz producto.
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
5
Tipos(II).
• Threads que utilizan recursos de modo mutuamente exclusivo, aunque sin
tener que coordinar sus actividades. Por ejemplo, threads que actualizan o
leen registros de una base de datos y que no pueden actuar
simultáneamente.
• Threads que deben de coordinar sus actividades, de modo que una de
ellas no puede empezar o continuar hasta que la otra haya realizado su
tarea. Los ejemplos más típicos son los de tipo productor-consumidor, en el
que este último tiene que esperar para realizar su función a que el
productor le haya preparado los datos y le avise de esa circunstancia.
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
6
Creación.

Hay dos modos de conseguir threads en Java. Una es
extender la clase Thread, la otra es implementando la
interface Runnable.
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
7
Creación extendiendo la clase Thread


El nuevo thread se crea extendiendo la clase Thread y
redefiniendo el metodo run().
Exemple:
public class MyThread extends Thread{
public void run(){
// código propio del thread
}
}
public static void main(){
Thread t= new MyThread();
t.start;
}
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
8
Creación implementando la interface Runnable

El constructor de la clase Thread recibe un argumento que
debe ser una instancia de una clase que implementa la
interface Runnable, implementando el metodo run() .
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
9
Creación implementando la interface Runnable(II)

Ejemplo:
public class ThreadTest{
public static void main(String args[]{
Xyz r = new XYZ();
Thread t = new Thread( r );
}
}
class Xyz implements Runnable {
int i;
public void run(){
while (true){
System.out.println(“Hello” + i++);
if (i==50) break;
}
}
}
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
10
Qué mecanismo usar?

Implementar la interfaz Runnable:
• Mejor diseño orientado a objetos. La clase thread solo deberá ser
extendida cuando se pretenda modificar o extender el comportamiento de
dicho modelo de ejecución.
• Herencia simple. Debido a la tecnología de Java no es posible extender
una clase cuando ésta ya ha sido extendida a la clase thread

Extender la clase Thread:
• Código más simple. En el método run la referencia this apunta a la
instancia del thread actual
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
11
Estados de un thread.
Otherwise
Blocked
sleep() timeout
thread join()
interrupt()
New
start()
sleep()
join()
Runnable
Running
wait()
Blocked in
objects wait()
pool
run()
Dead
synchronized()
lock
available
Blocked in
objects lock pool
notify()
interrupt()
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
12
Estados de un thread (II).
 Nuevo (New): El thread ha sido creado pero no inicializado (no se
ha ejecutado todavía el método start()), por lo que todavía no
puede ejecutarse.
 Ejecutable (Runnable): El thread puede estar ejecutándose,
siempre y cuando se le asigne tiempo de CPU. (Scheduler)
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
13
Estados de un thread (III).
 Muerto (Dead): La forma habitual de morir en un thread es
finalizando de ejecutar el método run(), bien por terminar su tarea,
bien dejando de cumplir una condición chequeada en dicho
método.
 Bloqueado (Blocked o Not Runnable): El thread podría estar
ejecutándose, pero hay algo que lo impide, como por ejemplo una
operación de E/S. Mientras un thread esté en este estado, no se
le asigna tiempo de CPU.
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
14
Planificación de threads.

La planificación de ejecución de threads se basa en el
modelo de prioridades y no utiliza el modelo de
segmentación por segmentos de tiempo.

Un thread continuará ejecutandose en la CPU hasta pasar
a un estado que no le permita seguir en ejecución. Se debe
asegurar que el thread permite la ejecución de otros
threads, esto se puede conseguir mediante llamadas al
método sleep().
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
15
Planificación de threads(II).

Ejemplo:
public class Xyz implements Runnable {
public void run() {
While(true){
// código del propio thread
try{
// permitimos la ejecución de otros threads
Thread.sleep(10);
} catch(InterruptedException e) {
// otro thread despierta a este thread
}
}
}
– Los threads pueden invocar al método interrupt() de otros threads
para reanimarlos.
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
16
Planificación de Threads(III).

Otro método para permitir la ejecución de otros threads es
el método yield() que permite la ejecución de otro thread
con la misma prioridad.

Las prioridades viene definidas por variables miembro de la
clase Thread, que toman valores int entre unos valores
MAX_PRIORITY y MIN_PRIORITY (entre 1 y 10), siendo la
prioridad por defecto NORM_PRIORITY(5).
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
17
Planificación de Threads(IV).
Cuando se crea un thread, hereda la prioridad del thread
que la ha creado.
 Para modificar la prioridad de un thread se utiliza el método
setPriority(int), y para obtener su valor el método int
getPriority().
 El algoritmo de distribución de recursos en Java:

• Es preemptive, es decir, el sistema ejecuta el thread de mayor prioridad
entre todos los que son Runnable (excepcionalmente puede ejecutarse
otro thread para evitar que algunos procesos “duerman” indefinidamente).
• Si varios threads en estado Runnable tienen la misma prioridad se van
ejecutando sucesivamente mediante permutación cíclica
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
18
Planificación de Threads(V).

Threads Daemon
– Los threads daemon llamodos servicios, se ejecutan con prioridad
baja y proporcionan un servicio básico a un programa o
programas cuando la actividad de la máquina es reducida.
– Un ejemplo de thread demonio que está ejecutándose
continuamente es el recolector de basura (garbage collector). E
– Un thread puede fijar su indicador de demonio pasando un valor
true al método setDaemon(). Si se pasa false a este método, el
thread será devuelto por el sistema como un thread de usuario.
No obstante, esto último debe realizarse antes de que se
arranque el thread (start()).
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
19
Control básico de threads.

Finalización del la ejecución de un thread.
– Cuando un thread acaba su ejecución y es finalizado , no puede
volver a ser ejecutado.
– Podemos detener un thread utilizando un flag que utiliza un
metodo run que debe terminar la ejecución.
• r.stopRunning() // r instancia de una clase que implementa runnable
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
20
Control básico de threads (II).

Verificación del estado thread isAlived()
• boolean isAlived(). Devuelve true si el thread ha sido inicializado con start y
no ha terminado el ciclo de ejecución.

Bloqueo de threads.
• sleep(). Permite detener un thread durante un determinado tiempo
• join(). Bloquea el thread actual, hasta que el thead sobre el cual ha sido
ejecutado el join termina.
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
21
Sincronización.

Existen muchas situaciones interesantes donde ejecutar
threads concurrentes que compartan datos y deban
considerar el estado y actividad de otros threads. Este
conjunto de situaciones de programación son conocidos
como escenarios 'productor/consumidor'; donde el
productor genera un canal de datos que es consumido por
el consumidor. Como los threads comparten un recurso
común, deben sincronizarse de alguna forma.
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
22
Sincronización. Uso de synchronized

Cada objeto tiene un “flag de bloqueo”
–
La palabra clave synchronized permite controlar el flag para
activar accesos exclusivos al objeto y cada objeto tendrá
asociada una cola de espera.
•
Se pueden declarar bloques de código synchronized.
synchronized ( variableCompartida )
{
// acceso al recurso
}
•
Métodos synchronized
public synchronized void nomMetode ()
{
// acceso al recurso
}
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
23
Sincronización. Uso de synchronized

El flag de bloqueo de un objeto se libera :
– Cuando el thread termina el bloque de código synchronized
– Cuando le bloque de código synchronized lanza una excepción.

Deadlock
– Dos threads esperando un flag de bloqueo
– No se detecta
– Se puede evitar:
• Decidir el orden de obtención de los bloqueos
• Seguir con rigurosidad ese orden
• Liberar los bloqueos en orden inverso
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
24
Sincronización. Comunicación entre threads

wait() y notify()
– Si un thread ejecuta una llamada wait() sobre un objeto x pausará
su ejecución hasta que otro thread ejecute la llamada a notify()
mediante el mismo objeto x.
– Para poder ejecutar tanto un wait() como un notify() el thread
debera disponer del flag de bloqueo, es decir, solo podrán ser
ejecutadis desde un bloque de codigo synchronized.
– Listas de espera o “pools”
• Cuando un thread ejecuta wait() se libera el flag de bloqueo y es colocado
en la lista de espera o pool del objeto (wait pool)
• Al ejecutar notify() un thread abitrario es movido de la lista de espera hacia
una lista de threads que esperan por el flag de bloqueo (lock pool).
notifyAll() despierta a todos los threads.
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
25
Sincronización. Monitores

Cuando un método synchronized se ejecuta adquiere un
monitor sobre el objeto. Cuando un thread tiene el monitor
del objeto ningún otro thread podrá ejecutar un metodo
synchronized.

Un thread sale del monitor cuando libera el flag de bloqueo
del objeto.
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
26
Sincronización. Monitores(II).


Un ejemplo típico del uso de monitores es el esquema de
productor/consumidor.
Aquí el productor y el consumidor son threads que acceden a la
región critica que es la tuberia o buffer. Esta tiene que tener sus
métodos protegidos mediante synchronized y tiene que hacer que los
threads se comuniquen mediante wait(), notify() y notifyAll().
Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
27
Bibliografia
Dossier Programación Java (Tomo 2) PUE
 http://server2.ok.cl/java/Cap7/thread.html
 http://www.medicina.ull.es/aula/tutoriales/java/monitors.html

Seminaris de CONCEPTES AVANÇATS DE SISTEMES OPERATIUS
Departament. d’Arquitectura de Computadors - UPC
28