Vous êtes sur la page 1sur 52

Sistemas Distribudos

Vtor Francisco Fonte Departamento de Informtica Universidade do Minho

(apontamentos originais de Paulo Srgio Almeida e Rui Carlos Oliveira)

Programao Concorrente 2013/2014

!"#$%#& Gruapo de Sistemas Distribu'dos

Programa Detalhado
Programao concorrente
Sistemas concorrentes Partilha de memria vs troca de mensagens Concorrncia em memria partilhada Seces crticas / excluso mtua Controlo de concorrncia por sw e hw Primitivas de CC pelo sistema operativo Ordem de execuo / variveis de condio Monitores!
! !"#$%#& Grupo de Sistemas Distribu'dos

Sistemas concorrentes
Processos correm concorrentemente num sistema:
Com pseudo-concorrncia, partilhando tempo de CPU; Com verdadeira concorrncia, num multiprocessador ou num sistema distribudo;

Com concorrncia os processos:


executam aes independentemente; correm com velocidades relativas imprevisveis; com partilha de tempo, as aes so intercaladas de um modo imprevisvel;
$ !"#$%#& Grupo de Sistemas Distribu'dos

Comunicao e sincronizao
Vrios processos podem querer cooperar num objectivo comum; Duas necessidades se vericam: comunicao e sincronizao; Comunicao:
passagem de informao entre processos; Exemplos:
um processo produz itens que vo ser usados pelo outro; um processo servidor recebe pedidos de clientes e devolve resultados;
& !"#$%#& Grupo de Sistemas Distribu'dos

Comunicao e sincronizao
Vrios processos podem querer cooperar num objectivo comum; Duas necessidades se vericam: comunicao e sincronizao; Sincronizao:
associado comunicao mas no necessariamente, processos podem ter que esperar antes de poder prosseguir; Exemplos:
esperar at item estar disponvel para ser consumido esperar at resposta ser devolvida; esperas ativas indesejveis;
( !"#$%#& Grupo de Sistemas Distribu'dos

Processos e Threads
Um processo comea com uma thread de execuo; outras podem ser criadas em seguida; As threads dos vrios processos correm concorrentemente; Cada processo possui o seu espao de endereamento privado; Todas as threads criadas dentro do mesmo processo:
partilham memria e recursos do processo; mantm o seu stack com variveis locais privadas
) !"#$%#& Grupo de Sistemas Distribu'dos

Processos e Threads

Threads podem ser vistas como processos leves que permitem cooperao eciente via memria; Podem tambm ser pedidos ao SO segmentos de memria partilhada entre processos; Vamos usar frequentemente a palavra processo no sentido lato, que engloba possvel partilha de memria;

!"#$%#& Grupo de Sistemas Distribu'dos

Partilha de memria vs. troca de mensagens

Consideramos duas grandes famlias de paradigmas na programao de sistemas concorrentes:


Sistemas com memria partilhada + primitivas de sincronizao; Sistemas com memria independente + troca de mensagens;

!"#$%#& Grupo de Sistemas Distribu'dos

Troca de mensagens
Diferentes primitivas:
Primitivas bsicas tipo send/receive; Cliente-servidor; Broadcast/multicast; Abstraes de comunicao de mais alto nvel; ex. comunicao em grupo, las de mensagens.

Comunicao sncrona ou assncrona; Comunicao orientada (ou no) conexo;


, !"#$%#& Grupo de Sistemas Distribu'dos

Concorrncia em memria partilhada


As aes dos processos so intercaladas de um modo imprevisvel; Acesso concorrente a dados partilhados pode levar a inconsistncia; So necessrias primitivas de controlo de concorrncia. Primitivas clssicas:
locks semforos monitores
#" !"#$%#& Grupo de Sistemas Distribu'dos

Corridas (race conditions) Corrida (race condition): Quando processos manipulam concorrentemente dados partilhados e o resultado depende da ordem dos acessos.
Exemplo:
Vrios processos acedem a um contador partilhado e cada processo pretende incrementar o contador:
contador = contador + 1

Suponha esta instruo traduzida para instrues mquina:


MOV contador, R0 ADD R0, 1 MOV R0, contador

Dado que a execuo dos processos pode ser intercalada de diferentes modos, o que pode acontecer ao contador?
## !"#$%#& Grupo de Sistemas Distribu'dos

Seces crticas
Um segmento de cdigo que acede a recursos partilhados uma seco crtica; As seces crticas tm que ser submetidas a controlo de concorrncia, caso contrrio podero surgir corridas; Uma seco crtica deve ser rodeada por cdigo de entrada (que obtm permisso para entrar) e de sada;
... codigo de entrada seccao critica codigo de saida ...
#! !"#$%#& Grupo de Sistemas Distribu'dos

Problemas das seces crticas


Uma soluo para o problema das seces crticas deve garantir:
excluso mtua: se um processo est a executar na sua seco crtica, mais nenhum o pode fazer; ausncia de deadlock: se vrios processos esto a tentar entrar na seco crtica, um deles deve inevitavelmente conseguir; ausncia de starvation: se um processo tenta entrar na seco crtica, inevitavelmente conseguir.
#$ !"#$%#& Grupo de Sistemas Distribu'dos

Problemas das seces crticas


Outra formulao para o problema
excluso mtua: se um processo est a executar na sua seco crtica, mais nenhum o pode fazer; progresso: se nenhum processo estiver a executar a seco crtica apenas os processos que executam o cdigo de sincronizao podem participar na deciso de quem entra; esta deciso no poder ser adiada indenidamente; espera limitada: existe um limite para o nmero de vezes que outros processos podem entrar passando frente de um processo que j executou o cdigo de sincronizao.
#& !"#$%#& Grupo de Sistemas Distribu'dos

Solues por software para seces crticas


Ser possvel encontrar uma soluo para o problema sem ajuda de hardware? Admitamos que podemos fazer esperas activas:
... while(...) ; // weco crtica ...

Poderemos obter o cdigo de entrada e sada da seco crtica manipulando variveis partilhadas de um modo cuidadoso?
#( !"#$%#& Grupo de Sistemas Distribu'dos

Solues por software para seces crticas

Na soluo, uma varivel partilhada:


int autorizacao = 1;

O processo i executa:
while (autorizacao == 0) ; autorizacao = 0 // // seco crtica // autorizacao = 1;

No uma soluo, pois no?

#)

!"#$%#& Grupo de Sistemas Distribu'dos

Alternncia estrita para 2 processos (rondas)


Uma varivel partilhada:
int vez = 0;

Processo i (0..1) executa:


while (true) { while (vez != i) ; // // seco crtica // vez = 1 - i; // // seco no-crtica // }

E se as seces no-crticas demoram tempos muito diferentes a executar?


#* !"#$%#& Grupo de Sistemas Distribu'dos

Soluo de Peterson para as seces crticas


Soluo clssica por software para 2 processos Duas variveis so partilhadas:
int vez = 0; boolean interessado[2] = { false, false };

O processo i (0..1) executa:


interessado[i] = true; vez = 1-i; while (interessado[1-i] && vez == 1-i) ; // // seco crtica // interessado[i] = false; // // seco no-crtica //

#+

!"#$%#& Grupo de Sistemas Distribu'dos

Soluo de Peterson para as seces crticas


Problemas
Restrita a 2 processos; Envolve espera activa; Pode no funcionar em arquiteturas de hardware modernas devido a cache e coerncia de caches;

A soluo pode ser estendida a n processos*

* Some Myths About Famous Mutual Exclusion Algorithms, K. Alagarsamy, 2003

#,

!"#$%#& Grupo de Sistemas Distribu'dos

Solues por hardware para seces crticas


Um padro geral de soluo pode ser obtido com locks:
adquirir lock seco crtica libertar lock

O problema pode ser passado para a implementao dos locks, com ajuda de hardware Diferentes possibilidades:
inibir interrupes instrues atmicas: test-and-set,swap,...
!" !"#$%#& Grupo de Sistemas Distribu'dos

Instruo atmica Test-and-set

Instruo que atomicamente:


coloca o valor de uma ag a verdadeiro e devolve o valor que a ag tinha previamente

Faz atomicamente o equivalente a:


boolean TestAndSet(boolean *pt) { boolean tmp = *pt; *pt = true; return tmp; }

!#

!"#$%#& Grupo de Sistemas Distribu'dos

Excluso mtua com test-and-set


Usando test-and-set fcil implementar excluso mtua; Flag lock comea a false; Cada processo faz:
while (TestAndSet(&lock)) ; // // seco critica // lock = false;

!!

!"#$%#& Grupo de Sistemas Distribu'dos

Excluso mtua com test-and-set


Usando test-and-set fcil implementar excluso mtua; Flag lock comea a false; Cada processo faz:
while (TestAndSet(&lock)) ; // // seco critica // lock = false;

A soluo satisfaz todos os requisitos?


!! !"#$%#& Grupo de Sistemas Distribu'dos

Excluso mtua espera limitada via test-and-set


Soluo para N processos, usa como itens partilhados, iniciados a false:
boolean espera[N]; boolean lock;

O processo i executa:
espera[i] = true; while (TestAndSet(&lock) && espera[i]) ; espera[i] = false; // seco critica j = (i + 1) % N; while (j != i && !espera[j]) j = (j + 1) % N; if (j == i) lock = false; else espera[j] = false;
!$ !"#$%#& Grupo de Sistemas Distribu'dos

Esperas ativas e o sistema operativo


As solues anteriores ainda envolvem esperas ativas; Estas podem prolongar-se enquanto outros processos executam as suas seces crticas: inaceitvel!; Soluo: o sistema operativo disponibiliza as primitivas (ex. adquirir e libertar lock) para rodear as seces crticas;
acquire(lock); // // seco crtica // release(lock);
!& !"#$%#& Grupo de Sistemas Distribu'dos

Implementao de primitivas pelo SO


As primitivas de controlo de concorrncia disponibilizadas pelo sistema operativo eliminam as esperas ativas; O kernel pode fazer um processo P passar ao estado bloqueado, no sendo escalonado e no consumindo tempo de processador; Mais tarde um processo Q invoca o libertar lock que trata de mudar o estado do processo P para pronto; O processo P pode ento entrar na seco crtica da prxima vez que for escalonado.
!( !"#$%#& Grupo de Sistemas Distribu'dos

Excluso mtua versus ordem de execuo


Na resoluo de problemas de controlo de concorrncia til distinguir duas situaes:
excluso mtua: quando vrios processos concorrem no acesso a recursos partilhados:
caso particular muito comum; processo apenas impedido de prosseguir temporariamente;

ordem de execuo: quando existem padres de cooperao e dependncia entre aces de processos:
um processo pode no poder prosseguir at uma dada aco de outro processo; processos bloqueiam-se voluntariamente e so libertados explicitamente por outros.
!) !"#$%#& Grupo de Sistemas Distribu'dos

Exemplo de excluso mtua: jantar dos lsofos


Cinco lsofos alternam entre pensar e comer, sentados volta de uma mesa:
existem 5 pratos na mesa; existem 5 garfos na mesa, um entre cada dois lsofos; um lsofo necessita de dois garfos para poder comer; um lsofo s pode pegar/pousar um garfo de cada vez.

Este um problema de excluso m"tua envolvendo vrios recursos, os garfos. Uma soluo tem que garantir:
segurana: cada lsofo s pode comer tendo dois garfos; ausncia de deadlock; ausncia de starvation;
!* !"#$%#& Grupo de Sistemas Distribu'dos

Jantar de lsofos
Filsofo i (0..4):
philosopher() { while (true) { think() pickup(i) eat() putdown(i) } } think() { sleep(random()); } eat() { sleep(random()); }

!+

!"#$%#& Grupo de Sistemas Distribu'dos

Jantar de lsofos

Soluo #0: sem controlo de concorrncia


pickup(i) { } putdown(i) { }

!,

!"#$%#& Grupo de Sistemas Distribu'dos

Jantar de lsofos

Soluo #1: lock global


boolean lock; pickup(i) { acquire(&lock); } putdown(i) { release(&lock); }

$"

!"#$%#& Grupo de Sistemas Distribu'dos

Jantar de lsofos

Soluo #3: garfo direito, garfo esquerdo


boolean lock[5]; pickup(i) { acquire(&lock[i]); acquire(&lock[(i+1)%5]); } putdown(i) { release(&lock[(i+1)%5]); release(&lock[i]); }

$#

!"#$%#& Grupo de Sistemas Distribu'dos

Jantar de lsofos

Soluo #4: garfo direito, garfo esquerdo


boolean lock[5]; pickup(i) { acquire(&lock[i]); sleep(1); acquire(&lock[(i+1)%5]); } putdown(i) { release(&lock[(i+1)%5]); release(&lock[i]); }

$!

!"#$%#& Grupo de Sistemas Distribu'dos

Jantar de lsofos
Soluo #5: pares direito/esquerdo; mpares esquerdo/direito
boolean lock[5]; pickup(i) { parity = i%2; acquire(&lock[(i+parity)%5]); acquire(&lock[(i+1-parity)%5]); } putdown(i) { parity = i%2; release(&lock[(i+1-parity)%5]); release(&lock[(i+parity)%5]); }

$$

!"#$%#& Grupo de Sistemas Distribu'dos

Ex. de ordem de execuo: produtor-consumidor


Existem dois tipos de processos:
produtor: produz itens de dados; consumidor: consome itens produzidos.

Itens so produzidos e consumidos para um bu#er partilhado, de tamanho limitado. Uma soluo tem que garantir que:
se o bu#er est vazio, um consumidor no pode prosseguir, tendo que car bloqueado; se o bu#er est cheio, um produtor no pode prosseguir, tendo que car bloqueado.

Estes problemas tambm podem envolver excluso mtua (manipulao do bu#er).


$& !"#$%#& Grupo de Sistemas Distribu'dos

Jantar de lsofos

Produtor-consumidor
producer() { while(true) { item = make(); put(item); } } consumer()(i) { while(true) { item = get(); consume(item); } }

$(

!"#$%#& Grupo de Sistemas Distribu'dos

Variveis de Condio
As VC so uma primitiva de sincronizao disponibilizada pelo SO que permite a um processo bloquear-se voluntariamente. Os processos testam um predicado sobre variveis de estado e decidem se bloqueiam. A uma VC sempre associado um lock. As VC no tm um valor que se leia ou escreva; o termo varivel vem do aspecto sintctico da declarao. So tambm conhecidas como condition queues.
$) !"#$%#& Grupo de Sistemas Distribu'dos

Variveis de Condio

$*

!"#$%#& Grupo de Sistemas Distribu'dos

Variveis de Condio
Associamos s VC nomes sugestivos das condies pelas quais o processo se decide bloquear, ex.:
cheio/vazio, garfo_ocupado, escritor_ativo

$*

!"#$%#& Grupo de Sistemas Distribu'dos

Variveis de Condio
Associamos s VC nomes sugestivos das condies pelas quais o processo se decide bloquear, ex.:
cheio/vazio, garfo_ocupado, escritor_ativo

Utilizamos normalmente primitivas wait e signal para manipular as VC:


Lock lock; Condition cheio; acquire(lock); while (lugares == 0) wait(cheio, lock); ... ... signal(cheio)
$* !"#$%#& Grupo de Sistemas Distribu'dos

Associao de um lock VC

Variveis de Condio

$+

!"#$%#& Grupo de Sistemas Distribu'dos

Variveis de Condio
A cada VC associada uma la f de processos que esto bloqueados na VC.

$+

!"#$%#& Grupo de Sistemas Distribu'dos

Variveis de Condio
A cada VC associada uma la f de processos que esto bloqueados na VC. Sendo o processo p a invocar o wait:
wait(cond, lock){ cond.f.append(p); release(lock); suspend();

$+

!"#$%#& Grupo de Sistemas Distribu'dos

Variveis de Condio
A cada VC associada uma la f de processos que esto bloqueados na VC. Sendo o processo p a invocar o wait:
wait(cond, lock){ cond.f.append(p); release(lock); suspend();

A primitiva signal seria:


signal(cond){ if cond.f != [] q = cond.f.pop(); ready(q);

$+

!"#$%#& Grupo de Sistemas Distribu'dos

Variveis de Condio
A cada VC associada uma la f de processos que esto bloqueados na VC. Sendo o processo p a invocar o wait:
wait(cond, lock){ cond.f.append(p); release(lock); suspend();

A primitiva signal seria:


signal(cond){ if cond.f != [] q = cond.f.pop(); ready(q);

Se no houver nenhum processo bloqueado em f o signal perde-se!


$+ !"#$%#& Grupo de Sistemas Distribu'dos

Ex.: bounded bu#er bloqueante


Lock lock; Condition vazio, cheio; int a[N], nitems, ...; int tirar(){ acquire(lock); while (nitems == 0) wait(vazio, lock); x = ... nitems--; signal(cheio); release(lock); return (x); } int por(int x) { acquire(lock); while (nitems == N) wait(cheio, lock); ... nitems++; signal(vazio); release(lock); }
$, !"#$%#& Grupo de Sistemas Distribu'dos

Monitores
O Monitor uma primitiva estruturada de controlo de concorrncia, de maior nvel de abstrao. Oferece um tipo abstrato de dados com controlo de concorrncia implcito em todas as operaes com excluso mtua. Associa automaticamente os dados e operaes ao cdigo de controlo de concorrncia. Disponibiliza variveis de condio implicita e/ou explicitamente.
&" !"#$%#& Grupo de Sistemas Distribu'dos

Ex.: bounded bu#er bloqueante com monitor


Monitor Buffer { Condition vazio, cheio; int a[N], nitems, ...; int tirar(){ while (nitems == 0) wait(vazio, lock); x = ... nitems--; signal(cheio); return (x); } int por(int x) { while (nitems == N) wait(cheio, lock); ... nitems++; signal(vazio); }

}
&#

!"#$%#& Grupo de Sistemas Distribu'dos

Ex.: bounded bu#er bloqueante com monitor


Monitor Buffer { Condition vazio, cheio; int a[N], nitems, ...; int tirar(){ while (nitems == 0) wait(vazio, lock); x = ... nitems--; signal(cheio); return (x); } int por(int x) { while (nitems == N) wait(cheio, lock); ... nitems++; signal(vazio); } Excluso mtua implcita

}
&#

!"#$%#& Grupo de Sistemas Distribu'dos

Caractersticas de implementao de Monitores


O acesso aos mtodos est sujeito a starvation Os locks so re-entrantes (ReentrantLock) Em monitores modernos (ex.: Java, Pthreads) quando executado signal:
o processo que invoca signal continua a sua execuo depois pode executar o processo acordado ou qualquer outro processo os testes de predicados do estado devero por isso utilizar while e no apenas if
&! !"#$%#& Grupo de Sistemas Distribu'dos

Correo de programas concorrentes


Existem dois tipos de propriedades:
Segurana: determinada propriedade (invariante de estado) sempre vericada:
ex: no esto dois processos na seco crtica; ex: um lsofo s pode comer com dois garfos; a correco corresponde a certos estados nunca serem atingveis.

Animao: determinada propriedade ser inevitavelmente vericada:


ex: se algum quer entrar na seco crtica acabar por faz-lo; ex: se um lsofo quer comer, acabar por comer; a animao diz respeito a certos estados acabarem por ser atingidos.
&$ !"#$%#& Grupo de Sistemas Distribu'dos

Algumas propriedades de animao


Casos particulares importantes de propriedades de animao:
Ausncia de deadlock: nunca atingido um estado do qual no haja sada (no possa ser feito progresso para um estado desejvel); Ausncia de livelock: nunca atingido um de vrios possveis estados dos quais no haja sada (para um estado desejvel). Ausncia de starvation: quando um dado processo tenta continuamente efetuar uma ao acaba por o conseguir. Ex: um processo s pode ser ultrapassado numa espera um nmero limitado de vezes.
&& !"#$%#& Grupo de Sistemas Distribu'dos

Vous aimerez peut-être aussi