41
Implementação de Sincronização Protocolos que usam busy waiting: Difíceis de projetar, compreender e provar corretos Complexos Variáveis usadas para sincronizar são idênticas às outras variáveis do programa ineficientes

Implementação de Sincronização n Protocolos que usam busy waiting: Difíceis de projetar, compreender e provar corretos Complexos Variáveis usadas

Embed Size (px)

Citation preview

Page 1: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Implementação de Sincronização

Protocolos que usam busy waiting: Difíceis de projetar, compreender e provar

corretos Complexos Variáveis usadas para sincronizar são

idênticas às outras variáveis do programa ineficientes

Page 2: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Solução

usar ferramentas especiais para ajudar a projetar protocolos de sincronização corretos, e bloqueiam processos em espera.

Page 3: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Semáforos

Foi uma das primeiras “ferramentas” Uma das mais importantes Torna fácil proteger regiões críticas Pode ser usado de forma disciplinada para

implementar sincronização de condição Podem ser implementados com busy-waiting

ou interagir com o escalonador de processos para obter sincronização sem busy-waiting

Page 4: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Semáforo

Tipo abstrato de dados, com duas operações: P(S)

Também chamada de wait Atrasa um processo até que um evento ocorra.

V(S)Também chamado de signalSinaliza a ocorrencia de um evento

Page 5: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Invariante do Semáforo

Para um semáforo s, seja nP o número de operações P completadas e nV o número de operações V completadas. Se init é o valor inicial de s, então, em todos os estados visíveis, nP nV + init

Execução de operações P esperam até que um número adequado de operações V tenha ocorrido

Page 6: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Representação de um Semáforo

Número não negativo s = init + nV – nP Invariante: s 0

Page 7: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Representação de um Semáforo

P (s) <await (s > 0) -> s := s – 1>

V (s) <s := s + 1>

Page 8: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Tipos de Semáforos

Semáforo genérico assume valores não negativos

Semáforo binário assume apenas valores 0 ou 1

Page 9: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Região Crítica sem_t S = 1;

void Pi {while (TRUE) { Non_Cr_S_i; P(S); Critical_S_i; V(S); }}

Page 10: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

A propriedade de exclusão mútua é satisfeita #CS é o número de processos em sua

região crítica provar que #CS + S = 1

#CS = nP(S) - nV(S) S = 1 + nV(S) - nP(S) S = 1 - #CS #CS + S = 1

como S >= 0, então #CS <= 1

Page 11: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

O programa não entra em deadlock os processos teriam que estar

suspensos em P(S) teríamos S = 0 e #CS = 0 mas já mostramos que #CS + S = 1

contradição

Page 12: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

não há starvation

Se P1 está suspenso, o semáforo deve ter 0

Pelo invariante do semáforo, P2 está na região crítica

Quando P2 sai da região crítica, executa V(S), que acorda um processo (P1)

Page 13: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Definições de semáforos

Blocked-set semaphore um sinal acorda um dos processos

suspensos Blocked-queue semaphore

os processos suspensos são mantidos em uma fila FIFO e são acordados na mesma ordem em que foram suspensos

Page 14: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Definições de semáforos

Busy-wait semaphore processos ficam testando o valor de S em

um loop de busy-wait. O teste é atômico.

Page 15: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Definições de semáforos

Strongly-fair semaphore se o semáforo é sinalizado infinatamente

frequente, em algum momento todos os processos esperando serão acordados.

Weakly-fair semaphore se o semáforo é mantido com um valor

maior que zero, em algum momento todos os processos esperando serão atendidos.

Page 16: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Provas

em um semáforo de busy-wait, pode ocorrer starvation P1 executa P(S) e entra na região crítica P2 encontra S = 0 e fica no loop P1 executa todo um ciclo, e reentra na

região crítica P2 encontra S = 0 e fica no loop

Page 17: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Provas

em um semáforo blocked-queue, é impossível ocorrer starvation suponha P1 bloqueado em S então existem no máximo N - 1 processos

na frente de P1 na fila para S

Page 18: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Provas

em um semáforo blocked-set, é possível ocorrer starvation para N >= 3 como não há garantia de qual processo

será acordado, se houverem pelo menos 2 processos bloqueados, um deles pode ser sempre o escolhido.

Page 19: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Barreiras sem_t barrier1 = 0;

sem_t barrier2 = 0;void P1 {while (TRUE) { ...; V(barrier1); P(barrier2); }}

void P2 {while (TRUE) { ...; V(barrier2); P(barrier1); }}

Page 20: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Problema do Produtor-Consumidor Problema de comunicação Produtores

geram dados com o procedimento Produce, que devem ser enviados aos consumidores

Consumidores ao receberem um dado fazem alguma

computação, com o procedimento Consume

Page 21: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Buffer de tamanho 1 int B;

sem_t empty = 1;sem_t full = 0;void Producer { int m; while (TRUE) { Produce(m); P(empty); B = m; V(full); }}

void Consumer {int m; while (TRUE) { P(full); m = B; V(empty); Consume(m);}

}

Page 22: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Buffer limitado (circular) int B[n]; int front = 0; int rear = 0;

sem_t empty = n;sem_t full = 0;void Producer { int m; while (TRUE) { Produce(m); P(empty); B[rear] = m; rear = (rear + 1) % n V(full); }}

void Consumer {int m; while (TRUE) { P(full); m = B[front];

front = (front + 1) % n V(empty); Consume(m);}

}

Page 23: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Buffer limitado – com vários produtores e consumidores

int B[n]; int front = 0; int rear = 0;sem_t empty = n; sem_t full = 0; sem_t mutexD = 0; sem_t mutexF = 0;

void Producer { int m; while (TRUE) { Produce(m); P(empty); P(mutexD); B[rear] = m; rear = (rear + 1) % n V(mutexD); V(full); }}

void Consumer {int m; while (TRUE) { P(full); P(mutexF); m = B[front];

front = (front + 1) % n V(mutexF); V(empty); Consume(m);}

}

Page 24: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Exclusão mútua seletiva

Jantar dos filósofos Processos competem por acesso a

conjuntos sobrepostos de variáveis compartilhadas

Leitores e Escritores Combinação de acesso concorrente e

exclusivo a variáveis compartilhadas

Page 25: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Jantar dos filósofos Cinco filósofos ao redor de uma mesa redonda Cada filósofo alterna entre comer e pensar O spaghetti está no centro da mesa Filósofos precisam de dois garfos para se

alimentar Existem 5 garfos, um entre cada par de

filósofos Evitar deadlock, e outras propriedades.

Page 26: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Jantar dos Filósofos

Fil. 2

Fil. 3

Fil. 4

Fil. 0

Fil. 1

Page 27: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Solução sem_t fork[4] = 1; void Philosopher[i] { /* filósofo 1 a 4 */

while (TRUE) { Think; P(fork[i]); P(fork[(i+1) % 5]); Eat; V (fork[i]); V (fork[(i+1) % 5]); }}

Page 28: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Solução 2 sem_t fork[4] = 1; void Philosopher[i] { /* filósofo 0 a 3 */

while (TRUE) { Think; P(fork[i]); P(fork[(i+1) % 5]); Eat; V (fork[i]); V (fork[(i+1) % 5]); }}

Page 29: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Solução 2 (cont.) sem_t fork[4] = 1; void Philosopher[4] { /* filósofo 4 */

while (TRUE) { Think; P(fork[0]); P(fork[4]); Eat; V (fork[4]); V (fork[0]); }}

Page 30: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Leitores e Escritores Dois tipos de processos: leitores e escritores,

compartilham o acesso a uma base de dados. Leitores lêem valores da base de dados. Escritores escrevem na base de dados. A Base de dados está inicialmente em um

estado consistente. Cada transação transforma a base de dados

de um estado consistente em outro.

Page 31: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Leitores e Escritores Para evitar interferência o escritor deve

ter acesso exclusivo à base de dados Se nenhum escritor estiver acessando a

base de dados, vários leitores podem ler concorrentemente a base de dados

Exclusão mútua seletiva

Page 32: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Solução Variáveis para controlar leitores e escritores

reading, writing[n]

Page 33: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Esboço da Solução int reading = 0; int nr = 0; int writing[n] = 0;

void Reader[i] { while (TRUE) { <nr++; if (nr == 1) {reading++};> read the database <nr--; if (nr == 0) {reading--};> }}void Writer[i] { while (TRUE) { <writing[i]++;> write the database <writing[i]--;> }}

Page 34: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Solução de grossa granularidade int reading = 0; int nr = 0; int writing[n] = 0;

void Reader[i] { while (TRUE) { <nr++; if (nr == 1) {await (SUM0) -> reading++};> read the database <nr--; if (nr == 0) {reading--};> }}void Writer[i] { while (TRUE) { <await (SUM 0) -> writing[i]++;> write the database <writing[i]--;> }}

Page 35: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Solução de grossa granularidade int reading = 0; int nr = 0; int writing[n] = 0;

sem_t mutexR = 1;void Reader[i] { while (TRUE) { P(mutexR); nr++; if (nr == 1) {<await (SUM0) -> reading++>}; V(mutexR); read the database P(mutexR); nr--; if (nr == 0) {< reading-- >}; V(mutexR); }}

Page 36: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Solução int nr = 0;

sem_t mutexR = 1; sem_t rw = 1;void Reader[i] { while (TRUE) { P(mutexR); nr++; if (nr == 1) {P(rw)}; V(mutexR); read the database P(mutexR); nr--; if (nr == 0) {V(rw)}; V(mutexR); }}

Page 37: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Solução void Writer[i] {

while (TRUE) { P(rw); write the database V(rw); }}

Page 38: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Solução Prioridade para os escritores

Outra solução: controlar quais processos estão em espera, e escolher outro tipo de prioridade contar número de leitores e escritores na região

crítica (nr, nw), número de leitores e escritores esperando (dr, dw).

Page 39: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Solução 2 int nr = 0; nw = 0;

sem_t e = 1; sem_t r = 0; sem_t w = 0;int dr = 0; int dw = 0;

Page 40: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Solução 2 void Reader[i] {

while (TRUE) { P(e); if (nw > 0) {dr++; V(e); P(r)}; nr++; if (dr > 0) {dr--; V(r)} else {V(e)}; read the database P(e); nr--; if (nr == 0 && dw > 0) {dw--;V(w)} else {V(e)}; }}

Page 41: Implementação de Sincronização n Protocolos que usam busy waiting:  Difíceis de projetar, compreender e provar corretos  Complexos  Variáveis usadas

Solução 2 void Writer[i] {

while (TRUE) { P(e); if (nr > 0 || nw > 0) {dw++; V(e); P(w)}; nw++; V(e); read the database P(e); nw--; if (dr > 0) {dr--;V(r)} else {if (dw > 0) {dw--;V(w)} else {V(e)}}; }}