Modelagem e implementação de programas concorrentes Aula 10 DCC-UFMG 2010
Bibliograa Andrews + Ben Ari
Da aula passada Se não posso adquirir o lock... Continuar tentando: Spinning, Busy wait (espera ocupada) Somente em multiprocessadores e para esperas curtas Blocking: ceder o controle ao escalonador, somente quando a espera for longa Espera ocupada > Contenção: Refere-se à disputa pelo acesso exclusivo a um recurso compartilhado.
Espera ocupada Pensar em desempenho. Abordagens: Minimizar o uso do bus pelas threads em espera ocupada Diminuir a latência de liberação/adquisição do lock Diminuir a latência na adquisição de locks livres Spinning em cache-> bom (em arquiteturas CC) Mas precisamos evitar invalidações desnecessárias.. -> Double checking (spinning sobre a cópia até o valor false for detectado e somente então executar o testandset()) ou Spinning sobre uma posição na memória distinta para cada processo (las) A melhor escolha depende da arquitetura e o problema em mãos...
Semáforos Dois colegas trabalham observando sinais de alarme numa central nuclear. Eles precisam se comunicar pelo telefone para avisar que vão almoçar, de forma que sempre tenha alguem observando os sinais. Considerando que não tem hora de inicio nem duração predeterminada para o lanche, quantos mensagens (ligações) iriam precisar?
Semáforos Variável protegida ou tipo de dados abstrato que permite controlar o acesso por vários processos a um recurso comum. Criados por Dijkstra para resolver o problema de sincronização em sistemas operacionais (the THE operating system) http://userweb.cs.utexas.edu/users/ewd/transcriptions/ewd01xx/ EWD123.html#3.2.%20The%20Synchronizing%20Primitives. Controle de acesso exclusivo a um recurso por 2 processos (1 na entrada (+1), 0 na saida (-1)) Controle de acesso exclusivo a um recurso por N processos?
Semáforos Variável protegida ou tipo de dados abstrato que permite controlar o acesso por vários processos a um recurso comum. Criados por Dijkstra para resolver o problema de sincronização em sistemas operacionais (the THE operating system) http://userweb.cs.utexas.edu/users/ewd/transcriptions/ewd01xx/ EWD123.html#3.2.%20The%20Synchronizing%20Primitives. Controle de acesso exclusivo a um recurso por 2 processos (1 na entrada (+1), 0 na saida (-1)) Controle de acesso exclusivo a um recurso por N processos? Funciona!
Semáforos Um maitre, M mesas em um restaurante e N usuários (N>M). Controle de acesso para até M processos a um recurso por N processos?
Semáforos Um maitre, M mesas em um restaurante e N usuários (N>M). Controle de acesso para até M processos a um recurso por N processos? Caso anterior: Accesso exclusivo: Considerar 0 caso especial, inicializar com 1, na entrada (-1), na saida (+1) P(s) atomic{bloqueia enquanto não positivo então decrementa o semárofo identicado como s} "prolaag"vem de "probeer te verlagen--> "try to decrease"by Dijkstra V(s) atomic{incrementa o semárofo identicado como s} (com isto acorda um processo em espera se tiver. QUEM?) (wait and signal, adquire and release) Controle de acesso para até M processos: Inicializado como M, na entrada (-1), na saida (+1))
Semáforos Semáforos de trem: livre para passar ou não. Construção concorrente de alto nível. Permitem resolver de forma simples o problema da seção crítica. Usualmente implementados pelo sistema operacional.
Semáforo denição: sem s := 0 # ou algum valor não negativo P(s): await (s>0) s = s-1; V(s): s = s+1;
Lembrando Possíveis estados de um processo: inativo --> pronto <--> executando --> terminado \ / <-bloqueado<- Pronto: pode executar a próxima instrução Bloqueado: Não pode executar até seu estado mudar para pronto (acordado, desbloqueado) por causa de uma ação externa espera ocupada <> bloqueado (em execução checando por variável)
Invariantes do semáforo k: valor inicial do semaforo, #signal(s): número de sinalizações signal(s) que tem sido executadas, #wait(s) número de instruções wait(s) executadas e terminadas. Teorema: Um semáforo S satisfaz as seguintes invariantes: 1. s >= 0 2. s = k + #signal(s) - #wait(s) Prova: Inicialmente verdadeiro: #signal(s) e #wait(s) = 0. Acesso ao semáforo somente através de signal e wait, então: toda vez que uma operação muda s a invariante se mantém (se se executa wait(s) s é decrementado e #wait aumenta na mesma medida, se um processo é desbloqueado #wait e #signal aumentam em 1).
Uso dos semáforos. Sinalização Thread A statement a1 signal(sem) Thread B wait(sem) statement b1 Rendezvous: As duas threads devem se encontrar em um ponto para prosseguir.
Uso dos semáforos. Sinalização Rendezvous: As duas threads devem se encontrar em um ponto para prosseguir. Exemplo: Garantir que dadas 2 threads A e B, as instruções são executadas de forma que a1 b2 e b1 a2, sem restringir demais. Thread A Thread B statement a1 statement b1 statement a2 statement b2
Solução Thread A statement a1 signal(aarrived) wait(barrived) statement a2 a1 b2 e b1 a2 Thread B statement b1 signal(barrived) wait(aarrived) statement b2
Uso dos semáforos. Exclusão mútua Garante que somente uma thread vai ter acesso ao recurso compartilhado de cada vez> Exclusão Mutua> MUTEX ou semáforo binário Para aceder o recurso, a thread deve adquirir o mutex. Valor inicial: 1. 1 signica mutex livre. 0 signica mutex ocupado. # initial value 1 to indicate CS is free sem mutex = 1; P(mutex); critical section V(mutex);
Para 2 processos A solução baseada em semáforos para o problema da seção crítica para 2 processos é correta: satisfaz a exclusão mútua no acesso à seção crítica e o programa é livre de deadlock e starvation. Provar EM: #CS + S = 1 é invariante: #CS = #wait(s) - #signal(s) invariante (da estrutura do programa) #wait(s) - #signal(s) = 1 - S (k=1) (de 2) > #CS = 1 - S e sabemos que S>=0 > exclusão mutua vale Deadlock: 2 processos bloqueados e s=0. Ninguem na seção crítica: #CS = 0. > #CS + S = 0 Contradiz invariante! Starvation: 1 processo p starving está bloqueado indenidamente de forma que S = 0. Por invariante, #CS = 1 - S, de forma que o outro processo q deve estar na seção crítica. Por progresso, q sai da CS e sinaliza, já que somente tem 2 processos p será o próximo a entrar na CS.
Semáforos fortes: politica FIFO (no starvation) Semáforos fracos: sem garantia FIFO (qualquer processo pode ser acordado a seguir)
Uso dos semáforos. Contadores ou semáforos gerais Garante que no máximo M threads terão acesso ao recurso compartilhado de cada vez Para aceder o recurso, a thread deve adquirir o mutex. Valor inicial: M. 0 signica mutex ocupado, a thread ca na espera.
Semáforos binários. PThreads mutex : semáforo binário com extras: controle de prioridade, erros e recursão. Release somente pela thread que chamou adquire. #include <pthread.h> int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex); int pthread_mutex_destroy(pthread_mutex_t *mutex); int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
Semáforos binários. PThreads #include <pthread.h> void foo() { pthread_mutex_lock(&foo_mutex); /* work. */ pthread_mutex_unlock(&foo_mutex); }
Semáforos Posix Kernel >= 2.6 mutex são mais rápidos processos ou threads. sem_open() cria novo semáforo ou abre existente sem_post() sem_wait() sem_close() sem_unlink(). remove s do sistema (senão fica lá até desliga
typet buf[n]; /* an array of some type T */ int front = 0, rear = 0; sem empty = n, full = 0; /* n-2 <= empty+full <= n */ process Producer { while (true) {... produce message data and deposit it in the buffer; P(empty); buf[rear] = data; rear = (rear+1) % n; V(full); } } process Consumer { while (true) { fetch message result and consume it; P(full); result = buf[front]; front = (front+1) % n; V(empty);... } } Figure 4.4 Bounded buffer using semaphores.
produtor/consumidor split binary semaphore sem empty = 1, full = 0 Producer: P(empty); deposit; V(full); Consumer: P(full); fetch; V(empty); propriedade fundamental: se são usados dessa forma (cada P está seguido de um V) então existe exclusão mutua entre um P e o próximo V 0 <= b1 +... + bn <=1
Uso dos semáforos. resource counting bounded buer generaliza a solução dos produtores/consumidores o que muda: representação do buer e valo inicial de empty 1 produtor and 1 consumidor multiplos produtores? multiplos consumidores? ambos? > acrescentar mutex: mutexp e/ou mutexc
Uso dos semáforos. leitores e escritores http://www.cs.arizona.edu/ greg/mpdbook/gures/ch04/4.3.pdf
Passagem de bastão Criamos: um semaforo e associado à entrada nos comandos atômicos (< await (B )S ; > ou < S :>) um semáforo sb e um contador db para cada condição B distinta (inicializados com 0) Cada < await (B )S ; > ca associado ao seguinte código: P(e) if (!B) { db++; V(e); P(sb);} S; SIGNAL onde o trecho?signal? corresponde ` passagem de bast?o para outros processos que estejam em espera
Uso dos semáforos. Barreiras The synchronization requirement is that no thread executes critical point until after all threads have executed rendezvous. You can assume that there are n threads and that this value is stored in a variable, n, that is accessible from all threads. When the rst n? 1 threads arrive they should block until the nth thread arrives, at which point all the threads may proceed. 1 n = the number of threads 2 count = 0 3 mutex = Semaphore(1) 4 barrier = Semaphore(0) count keeps track of how many threads have arrived. mutex provides exclu- sive access to count so that threads can increment it safely. barrier is locked (zero or negative) until all threads arrive; then it should be unlocked (1 or more). (2) barriers signaling sem arrive[1:n] = ([n] 0); # initially zeros to indicate that # conditions have not yet occurred P[i]:: V(arrive[i]); # signal I am here P(arrive[j]); # wait for partner P[j]: V(arrive[j]); # signal I am here P(arrive[i]); # wait for partner combine instances of these to form a dissemination or buttery
Dever de casa (3 pontos) Broadcast atômico: Imagine que existe um buer com n posições. Um produtor pode depositar mensagens somente quando houver uma posição livre e uma posição só pode ser reutilizada quando todos os C consumidores tiverem lido a mensagem. Cada consumidor deve receber as mensagens na ordem em que foram depositadas, mas pode fazê-lo no momento em que desejar. Programar com semáforos e mandar por email.
Dever de casa (3 pontos) 1. Produtores/consumidores (com buer limitado) 2. Leitores/escritores 3. O jantar dos lósofos 4. O jantar dos selvagens (andrews, the little book)