Upload
others
View
9
Download
0
Embed Size (px)
Citation preview
ditUPM
Algunosderechosreservados.EstedocumentosedistribuyebajolicenciaCrea9veCommonsReconocimiento-NoComercial-Compar9rIgual3.0Unported.hBp://crea9vecommons.org/licenses/by-nc-sa/3.0/deed.es
Programaciónconcurrente— Datoscompar9dosy exclusiónmutuaJuanAntoniodelaPuente <[email protected]>
20151026
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Referencias
•ScoBOaks&HenryWongJavaThreads O'ReillyMedia;3rded(2004)
•KathySierra&BertBates HeadFirstJava,ch.15O'ReillyMedia;2nded(2005)
2
Datoscompar9dos
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Variablescompar9das
• Lashebrasdeunprogramapuedenserindependientes‣ laejecucióndeunahebranoafectaaloquehaganlasdemáshebras
• …peroamenudoesmásinteresantequevariashebrascooperenpararealizarunafuncióncomún
• Unmecanismodecooperaciónmuycorrienteconsisteenusarvariablescompar9das‣ variablesalasque9enenaccesovariashebras‣ lashebraspuedenconsultar(leer)elvalordelavariableenunmomentodeterminadoomodificarlo(escribir)
4
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Ejemplo
• Doshebrasqueincrementanconcurrentementeelvalordeuncontador
• Problema:elresultadodependedeenquéordenseentrelacelaejecucióndelasoperacionesdecadahebra‣ estosellamacondicióndecarrera
5
hebra1 hebra2
contador
contador++ contador++
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Operacionesatómicas
• Laoperacióncontador++noseejecutadeunasolavez‣ sedescomponeen
registro = contador // registro es una variable temporal local de cada thread
registro = registro + 1 // incrementar el valor del registro
contador = registro // actualizar el valor del contador
• Lasoperacionesquenosepuedendescomponersellamanatómicas‣ contador++noesatómica‣ perolasoperacionesenquesedescomponesíloson
✓ enrealidaddependedelaimplementación(JVMylenguajedemáquina)
• Cuandovariashebrasseejecutanconcurrentementeseentrelazalaejecucióndesusinstruccionesatómicas
• Veamosdossecuenciasdeejecuciónposibles‣ suponemosqueinicialmentecontador==0
6
©2014JuanA.delaPuenteProgramaciónconcurrente—Exclusiónmutua
Secuenciasdeejecución(1)
7
registro=contador
hebra1
registro=registro+1
hebra2
registro=contador
registro=registro+1
contador=registro
contador=registro
registro ⟵ 0
registro ⟵ 1
registro ⟵ 0
registro ⟵ 1
contador ⟵ 1
contador ⟵ 1
contador == 0
contador == 1
©2014JuanA.delaPuenteProgramaciónconcurrente—Exclusiónmutua
Secuenciasdeejecución(2)
8
registro=contador
hebra1
registro=registro+1
hebra2
registro=contador
registro=registro+1
contador=registro
contador=registro
registro ⟵ 0
registro ⟵ 1
registro ⟵ 1
registro ⟵ 2
contador ⟵ 2
contador ⟵ 1
contador == 0
contador == 2
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Condicióndecarrera
9
• ¡Elresultadopuedeser1o2!‣ dependedelasvelocidadesdeejecuciónrela9vasdelashebras- “quiéncorremás”
• Elresultadodeunprogramanodebedependerdeestosdetalles‣ imposibledepreverdeantemano‣ cadaejecuciónesdis9nta- comportamientoindeterminado
‣ imposiblehacerensayos- cadavezunresultadodiferente
©2014JuanA.delaPuenteProgramaciónconcurrente—Exclusiónmutua
Ejemplo:variablecompar9da
public class PruebaCuenta {
static long cuenta = 0; /* variable compartida */
private static class Incrementa extends Thread { public void run () { for (int i = 0; i < 1000000; i++) { cuenta++; /* región crítica */ } } }
public static void main(String[] args) { new Incrementa().start(); /* hebra 1 */ new Incrementa().start(); /* hebra 2 */ System.out.println(“contador = “ + contador); } }
10
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Datoscompar9dosenobjetos
• Loscamposdedatosdeobjetosalosqueseaccededesdevariashebrastambiénsondatoscompar9dos‣ tambiénpuedendanlugaracondicionesdecarrera‣ daigualqueseaccedaalosdatosdirectamente(sisonvisibles)omediantemétodos
11
hebra1 hebra2
Contador
- cuenta
+ incrementar() + valor()
©2014JuanA.delaPuenteProgramaciónconcurrente—Exclusiónmutua
Ejemplo:objetosconestado(1)
public class Contador { private long cuenta = 0; /* estado */ public Contador (long valorInicial) { cuenta = valorInicial; } public void incrementar () { cuenta++; /* modifica el estado */ } public long valor () { /* devuelve el valor */ return cuenta; } }
12
©2014JuanA.delaPuenteProgramaciónconcurrente—Exclusiónmutua
Ejemplo:objetosconestado(2)
public class PruebaContador {
private static class Incrementa extends Thread { Contador contador;
public Incrementa (Contador c) { contador = c; }
public void run () { ... contador.incrementar(); /* región crítica */ ... } }
// continúa
13
©2014JuanA.delaPuenteProgramaciónconcurrente—Exclusiónmutua
Ejemplo:objetosconestado(3)
// continuación
public static void main(String[] args) { Contador contador = new Contador(0); Thread hebra1 = new Incrementa(contador); Thread hebra2 = new Incrementa(contador); /* las dos hebras comparten el objeto contador */ hebra1.start(); hebra2.start(); ... }
14
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Regionescrí9casyexclusiónmutua
• Lossegmentosdecódigoenqueseaccedeavariablescompar9dassellamanregionescrí9cas
• Paraevitarcondicionesdecarreraesprecisoasegurarlaexclusiónmutuaentrelashebrasenlasregionescrí9cas
• Cuandounahebraestáenunaregióncrí9caningunaotrapuedeaccederalosmismosdatos‣ primerounahebraefectúatodaslasoperacionesdesuregióncrí9ca,luegolaotra‣ elordennoimporta,siemprequenoseentrelacenlasoperacioneselementales
• Deestaformaseconsiguequelasoperacionesconvariablescompar9dasseanatómicas
15
Cerrojos
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Cerrojos
• Uncerrojo(lock)esunmecanismodesincronizaciónparaasegurarlaexclusiónmutua
• Puedeestarenunodeestosdosestados:‣ bloqueado(cerrado)‣ desbloqueado(abierto)
• Dosoperacionesatómicas‣ bloquear(lock)- siyaestábloqueado,lahebrasequedaesperando
‣ desbloquear(unlock)- sihayhebrasesperando,con9núaunadeellas
• Paraasegurarlaexclusiónmutua‣ bloquearcerrojo//esperasiestáocupado‣ regióncrí9ca‣ desbloquearcerrojo//sialguienesperabapuedecon9nuar
17
©2014JuanA.delaPuenteProgramaciónconcurrente—Exclusiónmutua
Ejemplo
18
registro=contador
hebra1
registro=registro+1
hebra2
registro=contador
registro=registro+1
contador=registro
contador=registro
registro ⟵ 0
registro ⟵ 1
registro ⟵ 1
registro ⟵ 2
contador ⟵ 2
contador ⟵ 1
contador == 0
contador == 2
bloquearcerrojocerrojo bloqueado
bloquearcerrojo
desbloquearcerrojo
desbloquearcerrojo
cerrojo desbloqueado
(cerrojo desbloqueado)
(cerrojo bloqueado)
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Problemasdeloscerrojos
• Esmuymecanismodemuybajonivelquenoesaconsejableu9lizardirectamente‣ hayquehacersiemprelock()yunlock(),eneseorden‣ puedesercomplicadoconestructurasdeprogramacomplejas‣ esfácilequivocarse,muchosproblemas
• Esmejordejarqueelcompiladorlohagapornosotros‣ integrarexclusiónmutuaconobjetos‣métodosybloquessincronizadosenJava
19
Monitores
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
ExclusiónmutuaenJava
21
• Javaproporcionamecanismosdesincronizaciónabstractos‣métodossincronizados‣ bloquessincronizados
• Definenpartesdelprogramaqueseejecutanenexclusiónmutua(regionescrí9cas)
• ElcompiladorylaJVMseencargandeges9onarloscerrojosdeformaimplícita
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Métodossincronizados
• Unmétodosincronizadoseejecutaenexclusiónmutuaconlosdemásmétodossincronizadosdelmismoobjeto
22
public class ContadorSincronizado {
private long cuenta = 0; /* estado */
public ContadorSincronizado (long valorInicial) { cuenta = valorInicial;
}
public synchronized void incrementar () {
cuenta++;
}
public synchronized long valor () { return cuenta;
}
}
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Métodossincronizados(con9nuación)
• Lasllamadasconcurrentesamétodossincronizadosseejecutanenexclusiónmutua
23
... public void run () { ... contador.incrementar(); /* región crítica */ ... } ...
• Cadaobjeto9eneasociadouncerrojo‣ Alempezaraejecutarunmétodosincronizadosebloqueaelcerrojo- siyaestababloqueado,lahebraqueinvocaelmétodosesuspende- lashebrasqueesperanestánenunalistaasociadaalobjeto(entryset)
‣ Alterminarsedesbloquea- sihayhebrasesperando,sereanudalaejecucióndeunadeellas
‣ Elcompiladorgeneraelcerrojoylosbloqueosydesbloqueos
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Implementación
24
lock
entryset
hebraen método
sincronizado
hebrasen espera
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Algunosdetalles
• Sóloseejecutanenexclusiónmutualosmétodossincronizados‣ siseolvidasincronizaralgúnmétodosepuedenproducircondicionesdecarrera
• Losmétodosdeclasetambiénsepuedensincronizar‣ seusauncerrojoparalaclaseyunoporcadaobjeto
• Losconstructoresnosepuedensincronizar‣ perosóloseinvocanalcrearunobjeto
25
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Monitores
• Unmonitoresunaclasequeencapsuladatoscompar9dosyoperacionesconlosmismos‣ todosloscamposdedatossehacenprivados- sólosepuedeaccederaellosatravésdemétodos
‣ todoslosmétodosestánsincronizados
• Esunesquemaclásicoparaconstruirprogramasconcurrentes‣ inventadoporPerBrinchHansenyC.AnthonyHoare(1974)
• Ventajas‣ lasincronizaciónseespecificaalmismo9empoquelosdatos‣ lashebrasqueaccedenalosdatosno9enenqueincluirningúnmecanismoespecial‣ consistenteconlosprincipiosdelaprogramaciónconobjetos
26
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Bloquessincronizados
• Permitendefinirregionescrí9casmutuamenteexclusivasconunagranularidadmenor
• Lasinstruccionesdelcuerposeejecutanenexclusiónmutua
• Seusaelcerrojoasociadoalobjeto• Puedeserú9lparamejorarlasprestaciones• Peroesmásdiwcildeusarquelosmétodossincronizados
27
synchronized(objeto) { instrucciones }
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Precauciones
• Hayqueiden9ficarbienlasregionescrí9cas‣ secuenciadeinstruccionesdondeseleeysemodificaelestadointernodelosobjetoscompar9dos‣ nosiempreesevidentedóndeestán‣ puedehaberregionescrí9casfueradelosdatosencapsuladossinosehandiseñadobienlosmétodos
• Hayquesincronizartodaslasregionescrí9cas‣ iden9ficarlasoperacionescondatoscompar9dosyrealizarlascomométodossincronizados
28
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Ejemplo(incorrecto)
29
public class Variable { private long valor = 0;
public Variable (long valorInicial) { valor = valorInicial; }
public synchronized void modificar(long v) { valor = v; }
public synchronized long valor() { return valor; } }
… Variable v = new Variable(0); … long x = v.valor(); // ¡La región crítica es x +=1; // todo esto!! v.modificar(x); // ¡No está sincronizada! ...
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Ejemplo(correcto)
30
public class Variable { private long valor = 0;
…
public synchronized void incrementar() { valor++; }
… }
… v.incrementar (); // Ahora está sincronizado …
Datosvolá9les
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Datosvolá9les
• Algunoscamposdedatossepuedendeclararvolatile ‣ indicaqueelvalorpuedecambiardesdeotrashebras‣ enmul9procesadoresnosehacencopiasprivadas‣ seaseguraquelaslecturasyescriturassonatómicas- ¡nadamás!
• Puedesereficientesiloúnicoquesehaceescambiarelvalorenunahebrayleerloenotra‣ porejemplo,parapararlaejecucióndeunahebra
32
©2014JuanA.delaPuenteProgramaciónconcurrente—Exclusiónmutua
Ejemplo
public class Tarea extends Thread {
private volatile boolean vivo = true;
public void run() { while (vivo) { // actividad concurrente } }
public void para() { vivo = false; } }
33
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Precauciones
• Sólosonatómicaslalecturaylaescrituradedatosprimi9vos
volatile int i; … i++; // ¡no es atómico, puede haber carreras
• Sisedeclarancomovolá9lesarraysuobjetos,loselementosindividualesnoestánprotegidos
34
Ejemplo
©2014JuanA.delaPuenteProgramaciónconcurrente—Exclusiónmutua
Ges9óndeunestacionamiento
• Variasentradasysalidas‣ sensoresqueavisancuandopasauncoche
• Supervisor‣muestralaocupacióndelestacionamiento(númerodecoches)
36
P
Entrada N
Entrada S Salida S
Sensor
Sensor Sensor
Supervisor
©2014JuanA.delaPuenteProgramaciónconcurrente—Exclusiónmutua
Diseño
37
«monitor»Parking
- n : natural+ entra+ sale+ ocupado: natural
«thread»Sensor
- acceso, id
«thread»Supervisor
©2014JuanA.delaPuenteProgramaciónconcurrente—Exclusiónmutua
Parking
public class Parking {
private int n = 0; // número de coches en el parking
// entra un coche por una de las puertas
public synchronized void entra (String puerta) {
n++;
}
// sale un coche por una de las puertas
public synchronized void sale (String puerta) {
n--;
}
// consulta
public synchronized int ocupado() {
return n;
}
}
38
©2014JuanA.delaPuenteProgramaciónconcurrente—Exclusiónmutua
Sensor
public class Sensor extends Thread {
private String id; private Parking p; private Acceso acceso; // ENTRADA o SALIDA
public Sensor(Parking p, String id, Acceso acceso) { this.p = p; this.id = id; this.acceso = acceso; }
@Override public void run() { while (true) { … // detecta un coche switch (acceso) { case ENTRADA: p.entra(id); break; case SALIDA: p.sale(id); break; } } } }
39
©2014JuanA.delaPuenteProgramaciónconcurrente—Exclusiónmutua
Supervisor
public class Supervisor extends Thread {
private Parking p;
public Supervisor(Parking p) {
this.p = p;
}
@Override
public void run() {
// comprueba el estado del parking cada 10 s
while (true) {
System.out.println("Número de plazas ocupadas: " + p.ocupado());
try {
sleep(10*1000);
} catch (InterruptedException e) {
System.err.println(e.toString());
}
}
}
}
40
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Crí9ca
• Elmonitorprotegeelestadointernodelestacionamiento‣ nohaycarrerasalactualizaroleer
• Peronoseaseguraqueelestadoseacorrecto‣ nodeberíanentrarcochessielestacionamientoestálleno
• Hacefaltaunmecanismoquepermitaimponerestascondiciones‣ sincronizacióncondicional
41
Resumen
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Resumen
• Elaccesoconcurrenteavariablescompar9daspuededarlugararesultadoserróneos‣ carreras
• Laformadeevitaresteproblemaesasegurarlaexclusiónmutuaentrelaszonasdondeseusanesasvariables‣ regionescrí9cas
• Elmecanismobásicoparaconseguirlaexclusiónmutuaeselcerrojo‣ bloqueoydesbloqueoatómicos
• EnJavaseusanmétodosybloquessincronizados‣ usanuncerrojoasociadoimplícitamenteacadaobjeto
43
Programaciónconcurrente—Exclusiónmutua ©2014JuanA.delaPuente
Resumen(con9nuación)
• Losmonitoressonclasesqueaseguranunaccesocorrectoaobjetoscompar9dos‣ todosloscamposdedatossonprivados‣ todoslosmétodosestánsincronizados- exceptolosconstructores
• Unaclasequesepuedeusarsinproblemasdesdevariashebrassedicequeessegura(threadsafe)
44