Multithreading and Thread Synchronization in Java

37
CONCEPTES AVANÇATS DE SISTEMES OPERATIUS Departament d’Arquitectura de Computadors (apunts de l’assignatura en format transparència) Multithreading and Thread Synchronization in Java Adolfo Alonso Puig [email protected] Eva Perales Laguna [email protected]

description

Adolfo Alonso Puig [email protected] Eva Perales Laguna [email protected]. Multithreading and Thread Synchronization in Java. Que es un thread en Java. Un thread representa una CPU virtual que ejecuta el código de un programa. Se compone de 3 partes: Procesador vrtual Código - PowerPoint PPT Presentation

Transcript of Multithreading and Thread Synchronization in Java

Page 1: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS Departament d’Arquitectura de Computadors

(apunts de l’assignatura en format transparència)

Multithreading and Thread Synchronization in Java

Adolfo Alonso Puig [email protected] Perales Laguna [email protected]

Page 2: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

2

Que es un thread en Java

Un thread representa una CPU virtual que ejecuta el código de un programa.

Se compone de 3 partes:

– Procesador vrtual– Código– Datos

Page 3: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

3

Creación de un thread (I)

Tenemos dos posibilidades a la hora de crear threads:

– Crear una instancia de una clase que implemente el interface Runnable

• Debe proveer una implementación del método run()

miClase th= new miClase();

Page 4: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

4

Creación de un thread (II)

– Extender la clase Thread• Redefinición del método run() de la superclase

public class MyThread extends Thread{

}

MyThread th= new MyThread();

• Problema: Java sólo permite la herencia simple,no será posible extender ninguna otra clase cuando extendemos la clase Thread.

Page 5: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

5

Inicio de un thread

Al crear un thread no iniciamos su ejecución de forma automática. Para iniciarlo debemos invocar a su método start()

th.start();

El thread esta preparado para ejecutarse

Page 6: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

6

Control básico de threads (I)

Finalización de un thread– Podemos detener un thread utilizando un flag que indique a su

método run que debe terminar su ejecución.Una vez finalizado no puede volver a ser ejecutado

– En versiones anteriores de JDK se usaba el método stop() pero esta “Deprecated”.

Verificación del estado de un thread– Para saber si un thread puede ser elegido para ejecución

utilizamos el método isAlive()

Page 7: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

7

Control básico de threads (II)

Bloqueo de un thread– El método sleep() permite detener un thread durante un periodo

de tiempo definido por el usuario.

– El método join() bloquea el thread actual hasta que el thread sobre el cual ha sido ejecutado el join termina.

– En versiones anteriores de JDK se proporcionaba el método suspend() que bloqueaba el thread hasta que fuera nuevamente activado por el método resume()

Page 8: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

8

Estados de un thread

Page 9: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

9

Planificación de threads

Se basa en el modelo de prioridades y no en la multiplexacion del tiempo de CPU (“timeslicing”)

Para decidir que thread se ejecuta el planificador se fija en la prioridad de cada uno y elige el de prioridad más alta

El método yield() puede ser utilizado para permitir a otros threads con la misma prioridad la posibilidad de ejecutarse

Page 10: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

10

Prioridades

La prioridad de un thread puede tener un valor entero entre MIN_PRIORITY y MAX_PRIORITY (constantes de la clase java.lang.Thread)

La prioridad de un nuevo thread es la misma del thread en ejecución.

El método getPriority() devuelve el valor actual de la prioridad del thread.

El método setPriority() modifica la prioridad del thread

Page 11: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

11

Problemas con threads: Race condition

Es el problema más común y a la vez el más insidioso que se produce con los threads. Aparece cuando dos o más threads acceden al mismo recurso a la vez.

El problema se genera de forma aleatoria produciendo un abrazo mortal (deadlock) entre todos los threads, datos inconsistentes o fallo del programa.

Page 12: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

12

Ejemplo de race condition (I)

class UnsafeLogger{ // recurso crítico, podria ser una lista enlazada, vector o cualquier recurso private File m_file;

public void write ( String s ) { // tratamiento de ficheros simplificado m_file.open ( "filename.log" ); m_file.write ( s ); m_file.close ( ); }}

Page 13: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

13

Ejemplo de race condition (II)class Writer extends Thread { private UnsafeLogger m_log; private String m_threadID; Writer ( UnsafeLogger log, String threadID ) { m_log = log; m_threadID = threadID; }

public void run ( ) { while( true ) { m_log.write ( m_threadID ); m_log.write ( " is alive\n" ); } }}

Page 14: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

14

Ejemplo de race condition (III)

class MainClass { public static void main ( ) { UnsafeLogger log = new UnsafeLogger ( ); Writer writer1 = new Writer ( log, "thread1" ); Writer writer2 = new Writer ( log, "thread2" );

// inicia los threads writer1.start ( ); writer2.start ( ); }}

Page 15: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

15

Posibles ejecuciones del ejemplo (I)

Ciclo thread 1 thread 2 Nota1 Abre el fichero2 Escribe el string3 Cierra el fichero4 Abre el fichero5 Escribe el string6 Cierra el fichero

Salida: Thread1 is alive Thread2 is alive

El código parece funcionar funcionar correctamente

Page 16: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

16

Posibles ejecuciones del ejemplo (II)

Ciclo thread 1 thread 2 Nota1 Abre el fichero2 Abre el fichero3 Escribe el string4 Escribe el string5 Cierra el fichero6 Cierra el fichero Suponiendo que cerrar un fichero ya cerrado no da problemas

Salida: Thread1 Thread2 is alive is alive

Funcionara pero no de forma correcta al intercalar las salidas de los threads.

Page 17: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

17

Posibles ejecuciones del ejemplo (III)

Ciclo thread 1 thread 2 Nota1 Abre el fichero2 Escribe el string3 Abre el fichero Suponiendo que abrir un fichero ya abierto no da problemas4 Cierra el fichero5 Escribe el string Falla!6 Cierra el fichero

El thread2 intenta escribir en un fichero cerrado, falla el programa.

Page 18: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

18

Flag de bloqueo de un objeto

El método synchronized permite controlar este flag para activar el acceso exclusivo al objeto.

Permitirá bloquear recursos compartidos para controlar el acceso de los threads sobre estos.

CriticalResource m_criticalResource;// bloquea el recurso antes de que sea usadosynchronized( m_criticalResource ){

// uso el recurso}// fin del desbloqueo del recurso

Page 19: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

19

Solución del ejemplo con synchronized

Aplicamos el método synchronized para intentar solucionar el problema:

public void write( String s ){

synchronized( m_file ) {

m_file.open( "filename.log" ); m_file.write( s ); m_file.close();

}}

Page 20: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

20

Posible ejecución del ejemplo con synchronizedCiclo thread 1 thread 2 Nota

1 Bloquea el fichero2 Abre el fichero3 Escribe en el fichero4 Intenta bloquear el fichero Se esperara ya que el

fichero ya esta bloqueado5 Cierra el fichero Sigue esperando6 Desbloquea el fichero Se produce al finalizar el

synchronized7 Bloquea el fichero8 Abre el fichero9 Escribe en el fichero

10 Cierra el fichero11 Desbloquea el fichero

Salida: Thread1 Thread2 is alive is alive

Aun se puede producir esta situación

Page 21: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

21

Solución final

Con el código proporcionado no hay manera evitar que se pueda dar la salida intercalada utilizando 2 threads.

Modificaremos las instrucciones m_log.write( m_threadID ); m_log.write( " is alive\n" );

Por una operación atómica de escritura

String logMessage = m_threadID + " is alive\n";m_log.write( logMessage );

Page 22: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

22

Problema de lectores/escritores

Base de datos accedida por una serie de procesos lectores y otros escritores que la modifican.

Los lectores pueden acceder de forma simultanea.

Los escritores deben hacerlo de forma individual y mientras modifiquen la base de datos esta no puede ser accedida por ningún lector.

Page 23: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

23

Solución intuitiva 1 (I)

Object readLock = new Object();Object writeLock = new Object();int readers = 0;

public void read(){

synchronized (readLock);{

if ( readers == 0 ){

synchronized(writeLock);...

Page 24: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

24

Solución intuitiva 1 (II)

Esta solución es incorrecta. Cuando salimos de la región synchronized (writelock), desaparece el bloqueo para los escritores.

Synchronized no es realmente un semáforo sino que sólo una región crítica .

Page 25: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

25

Solución intuitiva 2 (I)public void read(){synchronized (m_lock){// lectura}}public void write(){getDataToWrite();synchronized(m_lock){// escritura}}

Page 26: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

26

Solución intuitiva 2 (II)

Esta solución funciona, aunque no hace exactamente lo que se esperaba de ella.

Protege correctamente las regiones críticas, pero no permite el acceso a varios lectores de forma simultanea a la base de datos, así que las ventajas del multithreading desaparecen.

Page 27: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

27

Solución con espera activa (I)public class CriticalResourceUsingSynchronized {

private Object m_readLock = new Object(); private int m_reading = 0;

public int read() {int readData = 0;

synchronized( m_readLock ) { m_reading++; } // lectura synchronized( m_readLock ) { m_reading--; }

return readData;}

Page 28: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

28

Solución con espera activa (II) public void write ( int x ) { boolean succeeded = false;

while ( !succeeded ) { synchronized ( m_readLock ) { if ( m_reading == 0 ) { // escritura succeeded = true; } }

if ( succeeded == false ) Thread.currentThread().yield();

}}}

Page 29: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

29

Comunicación entre threads

Las esperas activas no son eficientes y malgastan una serie de recursos inútilmente.

Existen dos métodos, wait() y notify() que permiten la comunicación entre threads.

Si un thread ejecuta la llamada wait() sobre un objeto x pausará su ejecución hasta que otro thread ejecute una llamada a notify() mediante el mismo objeto x.

Page 30: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

30

Monitores (I)

La coordinación de threads que acceden a datos comunes puede resultar muy compleja. La información debe mantenerse en un estado consistente.

Los monitores mantienen un flujo de comunicación entre los threads

Page 31: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

31

Monitores (II)

El esquema básico de los monitores es el siguiente:

Object o = new Object();

synchronized(o) { o.wait();

}

synchronized(o) { o.notify();

}

Page 32: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

32

Monitores (III)

Los métodos wait y notify nos permiten implementar bloqueos reales en Java.

Para ello podemos utilizar la clase Lock, que implementa un semáforo booleano.

Page 33: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

33

Clase Lock (I)class Lock extends Object {

private boolean m_bLocked = false;public synchronized void lock() {

if( m_bLocked ) { do { try { wait(); } catch( Exception e ) { e.printStackTrace(); } } while ( m_bLocked ); } m_bLocked = true; }

Page 34: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

34

Clase Lock (II)

public synchronized void releaseLock() { if( m_bLocked ) { m_bLocked = false; notify(); } }

public synchronized boolean isLocked() { return m_bLocked; }

}

Page 35: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

35

Solución con la clase Lock (I) import Lock;

public class CriticalResourceUsingLocks { private Lock m_readLock = new Lock(); private int m_reading = 0; private Lock m_writeLock = new Lock();

public int read() { int readData = 0;

m_readLock.lock(); if( m_reading == 0 ) m_writeLock.lock(); m_reading++; m_readLock.releaseLock();

Page 36: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

36

Solución con la clase Lock (II)// lectura

m_readLock.lock(); m_reading--; if( m_reading == 0 ) m_writeLock.releaseLock(); m_readLock.releaseLock(); return readData; }

public void write( int x ) { m_writeLock.lock();

// escritura

m_writeLock.releaseLock(); }}

Page 37: Multithreading and Thread Synchronization in Java

CONCEPTES AVANÇATS DE SISTEMES OPERATIUS

Departament. d’Arquitectura de Computadors - UPC

37

Bibliografía

http://journal.iftech.com/articles/threadsync/

http://developer.java.sun.com http://sunsite.dcc.uchile.cl/java http://java.sun.com/docs/books/tutorial/index.html