Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima...

107
Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho ( [email protected] )

Transcript of Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima...

Page 1: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Sistemas DistribuídosAula 04 – Programação Multithread/Paralela

Prof. Hélio de Sousa Lima Filho ([email protected])

Page 2: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Referencial Bibliográfico

• Coulouris, George; Dollimore, Jean e Kindberg, Tim. Sistemas Distribuídos: conceitos e projeto.

• Ribeiro, Uirá. Sistemas Distribuídos, Desenvolvendo aplicações de Alta Performance no Linux.

2Sistemas Distribuídos

Page 3: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Sumário

1. Arquiteturas, Conceitos e Características, 2. Implementação de Seções Críticas3. Semáforos e Monitores4. Estudo de Caso: Java

3Sistemas Distribuídos

Page 4: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Sumário

1. Arquiteturas, Conceitos e Características 2. Implementação de Seções Críticas3. Semáforos e Monitores4. Estudo de Caso: Java

4Sistemas Distribuídos

Page 5: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Programação Concorrente

• Podemos dividir os programas computacionais em duas categorias distintas:– Programas seqüenciais

• único fluxo execução– Programa concorrentes

• vários fluxos execução

• Em nossa disciplina, iremos dar foco apenas a programação concorrente.

5Sistemas Distribuídos

Page 6: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Programação Concorrente

• A programação concorrente, pode ser dividida em 3 grupos distintos:– Multithread– Paralelos – Distribuídos

6Sistemas Distribuídos

Page 7: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Programação Concorrente Multithread

• Thread (processos leves)– É uma parte de um programa que é

executado concorrentemente.– É composto por 5 partes:

• Segmento de código• Segmento de dados• Pilha• Segmento de entrada e saída• Tabela de sinais

7Sistemas Distribuídos

Page 8: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Programação Concorrente Multithread

• Multithread:– núm. fluxos execução > núm. processadores– Objetivo:

• fazer várias coisas ao mesmo tempo reduzindo o gasto desnecessário de memória de processamento.

– Como?• Através do compartilhamento do segmento de código,

segmento de dados e espaço de endereçamento.

– Exemplos:• GUI, SO, SGBD, servidores Web

8Sistemas Distribuídos

Page 9: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Programação Concorrente Multithread

9Sistemas Distribuídos

Gerenciador de

Processos

Thread A

Thread B

“Main” Thread

Pthread Join “A”

Pthread Join “B”

InstruçãoInstrução

Pthread Create

Pthread Create Instrução

Instrução

Instrução

Exit

Instrução

Instrução

Instrução

Exit

Page 10: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Programação ConcorrenteProgramas Paralelos

• Programas Paralelos:– núm. fluxos execução = núm. processadores

• Objetivo: – fazer uma tarefa mais rápido.

• Exemplos: – multiplicar matrizes, – previsão tempo, – processar/gerar imagem, – simulações

10Sistemas Distribuídos

Page 11: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Programação ConcorrenteProgramas Distribuídos

• Programas distribuídos– fluxos de execução em nodos de uma rede– Objetivo:

• “compartilhar recursos”– Exemplo:

• aplicações Cliente/Servidos– E-mail – web– dados

11Sistemas Distribuídos

Page 12: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Programas ConcorrentesComunicação/Sincronização

• Mem. compartilhada – Multithreads e Paralelos

• Troca de mensagens– todos os 3 tipos

12Sistemas Distribuídos

Page 13: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Programas ConcorrentesComunicação/Sincronização

• A sincronização é a principal dificuldade dos programas concorrentes– Seção Crítica

• Código no qual apenas um processo pode executar por vez• Técnicas

– Exclusão Mútua: • assegurar que seções críticas não sejam executadas ao

mesmo tempo• Dois processos não podem gravar ao mesmo tempo no

buffer– Sincronização condicional:

• atrasar a execução até que uma condição seja verdadeira

• Canal só pode ler dados se buffer cheio

13Sistemas Distribuídos

Page 14: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Conceitos

• Fluxos execução assíncronos: – cada fluxo de execução tem a sua própria

“velocidade”• Processo:

– fluxo execução + espaço de endereçamento próprio

• Thread (“processos leves”): – fluxo execução + espaço de endereçamento

compartilhado

14Sistemas Distribuídos

Page 15: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Arquiteturas

• Arquiteturas Monoprocessadas:– Programação seqüencial com interrupções– Núcleo de multiprogramação (SO, VM, ou

biblioteca) cria um modelo de programação assíncrono

– Vários processos compartilham CPU• Arquiteturas Multiprocessadas:

– Memória Compartilhada– Memória Distribuída

15Sistemas Distribuídos

Page 16: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Arquiteturas Multiprocessadas Memória compartilhada

• Podem ser:– UMA (Uniform Memory Access Time)– NUMA (Non-Uniform Memory Access Time)

• Comunicação– via memória compartilhada ou troca de

mensagens• Vantagem

– barramento de alta velocidade, memória compartilhada facilita programação

• Desvantagem– limitação no número de nodos

16Sistemas Distribuídos

Page 17: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Arquiteturas Multiprocessadas Memória compartilhada

17Sistemas Distribuídos

...Memória

Rede de Interconexão

CacheCache

Memória

CPUCPU

...

Page 18: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Arquiteturas Multiprocessadas Memória Distribuída

• Processos podem acessar apenas memória local• Processos se comunicam por troca de msgs• Vantagem

– Escalabilidade• Desvantagem

– Dificuldade de programação• Memória Compartilhada Distribuída (DSM)

– Abstração de um espaço de endereçamento único criada pelo SO

– SO mapeia “endereço virtual” para endereço físico de um processador

– Desvantagem• Custo de comunicação

18Sistemas Distribuídos

Page 19: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Arquiteturas Multiprocessadas Memória Distribuída

19Sistemas Distribuídos

Memória

Rede de Interconexão

CacheCache

Memória

CPUCPU

...

Page 20: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Arquiteturas Multiprocessadas - Clusters

• Computadores “comuns” conectados em rede

• Cada nodo tem sua CPU, memória e SO• Vantagens

– escalabilidade, custo, tolerância a falhas• Desvantagens

– conexão em rede e administração• Custo de administração similar ao de n

máquinas independentes

20Sistemas Distribuídos

Page 21: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Arquiteturas Multiprocessadas memória compartilhada

• Idéia: – calcular produtos internos paralelamente– Variáveis compartilhadas:

• double a[n,n], b[n,n], c[n,n]

21Sistemas Distribuídos

Page 22: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Arquiteturas Multiprocessadas memória compartilhada

• Código da multiplicação:process row [i= 0 to n-1] % cria n processos for j:= 0 to n-1 do c[i,j]= 0; for k:= 0 to n-1 do c[i,j] = c[i,j] + a[i,k] * b[k,j]

• Na solução acima, cada processo gera uma linha da resposta

22Sistemas Distribuídos

Page 23: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Arquiteturas Multiprocessadas memória compartilhada

• Outra solução: computar cada produto interno em paraleloprocess [i= 0 to n-1, j= 0 to n-1] % cria n*n proc c[i,j]= 0; for k:= 0 to n-1 do c[i,j] = c[i,j] + a[i,k] * b[k,j]

23Sistemas Distribuídos

Page 24: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Arquiteturas Multiprocessadas memória distribuída

• Agora o mesmo problema de multiplicação de matrizes em memória distribuída

process worker[i=0 to n-1] { double a[n]; double b[n,n]; double c[n]; receive initial values for vector a and matrix b; for [j=0 to n-1] { c[j]=0.0; for [k=0 to n-1] c[j]=c[j] + a[k]*b[k,j]; } send result vector c row to the coordinator process; }

24Sistemas Distribuídos

Page 25: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Arquiteturas Multiprocessadas memória distribuída

process coordinator { double a[n,n]; double b[n,n]; double c[n,n]; initialize a and b; for [i=0 to n-1] { send row i of a to worker[i]; send all of b to worker[i]; } for [i=0 to n-1] receive row i of c from worker[i]; print the result matrix c; }

25Sistemas Distribuídos

Page 26: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

IPC via Unix Pipes

• Pipes– mecanismo de IPC (Inter Process Communication)– Fila de bytes unidirecional residente no kernel

• Criação de um pipe:– int d [2];– int pipe (d);

• Escrita e leitura– int write (d[1], “hello world”);– int read (d[0], buffer, tam_buffer);

• Pipes entre processos diferentes:– Criado por processo pai; em seguida, pai executa um fork– Pai e filho passam a compartilhar o pipe– Somente pode ser usado entre processos pai e filho ou entre

“processo irmãos”

26Sistemas Distribuídos

Page 27: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Produtores/Consumidores via Pipes

void main () { // comunicação de pai para filho

int n, d[2]; pid_t pid; char line [MAX_LINE]; if (pipe (d) < 0) printf (“Erro na criação

do pipe”); else if ((pid = fork()) < 0) printf (“Erro no fork”);

27Sistemas Distribuídos

else if (pid > 0) { // processo pai: pid= PID filho

close (d[0]); write (d[1], “hello world\n”); } else { // processo filho: pid =

0 close (d[1]); n= read (d[0], line,

MAX_LINE); // síncrona cout << line; }}

Page 28: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Sumário

1. Arquiteturas, Conceitos e Características 2. Implementação de Seções Críticas3. Semáforos e Monitores4. Estudo de Caso: Java

28Sistemas Distribuídos

Page 29: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Processos e Sincronização

• Estado– valor das variáveis de um processo em um instante

• Processo executa uma seqüência de comandos– Comando: seqüência de ações atômicas

• Ação atômica:– ação que inspeciona/altera estado de forma indivisível– Não podem ser quebradas em ações mais simples

• Exemplos: – instruções de máquina que acessam palavras da memória

• Execução de programa concorrente gera uma história: – s0 s1 ... sn (si: ação atômica)– Histórias podem variar de execução para outra

29Sistemas Distribuídos

Page 30: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Processos e Sincronização

• Exemplo (atribuições e leituras atômicas):

30Sistemas Distribuídos

HORA PESSOA A PESSOA B06:00 Olha a geladeira: sem leite

06:05 Sai para a padaria

06:10 Chega na padaria Olha a geladeira: sem leite

06:15 Sai da padaria Sai para a padaria

06:20 Chega em casa: guarda o leite Chega na padaria

06:25 Sai da padaria

06:30 Chega em casa: Ops!

Page 31: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Processos e Sincronização

• O problema anterior ocorre porque a pessoa não sabia o que a outra estava fazendo

• A solução para este problema envolve dois conceitos– Exclusão mútua: apenas um processo pode

fazer alguma coisa em determinado momento– Seção Crítica: uma seção crítica de código no

qual apenas um processo pode executar de cada vez

31Sistemas Distribuídos

Page 32: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Processos e Sincronização

• Exemplo (atribuições e leituras atômicas):– int y= 0, z= 0;– P1:: x = y +z; P2:: y= 1; z= 2;

• Algumas histórias possíveis – rd y rd z x= y+z y= 1 z= 2 x= 0– y= 1 rd y rd z x= y+z z= 2 x= 1– rd y y= 1 z= 2 rd z x= y+z x= 2– y= 1 z= 2 rd y rd z x= y+z x= 3

32Sistemas Distribuídos

Page 33: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Sincronização

• Sincronização– Restringe as histórias possíveis

• Exclusão mútua– requer a criação de ações atômicas via software – Uma ação atômica ”de maior granularidade” é

chamada de seção crítica• Exemplo: < ... > cria uma seção crítica

int y= 0, z= 0;P1:: <x = y +z;> P2:: <y= 1; z= 2;>

• Histórias possíveis:– rd y ; rd z ; x= y+z y= 1 ; z= 2 x= 0– y= 1 ; z= 2 rd y ; rd z ; x= y+z x= 3

33Sistemas Distribuídos

Page 34: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Sincronização

• Sincronização condicional: – atrasar uma ação atômica até que uma

condição seja verdadeira• Até que o estado atenda uma condição

– Propriedade: • condição que é verdadeira em qualquer história

de um programa concorrente– Podem ser de dois tipos: safety e liveness

34Sistemas Distribuídos

Page 35: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Sincronização condicional Safety e Liveness

• Safety: – propriedades que asseguram a não ocorrência de um estado

indesejável– O programa nunca entra em um estado inconsistente

• Liveness: – propriedade que assegura a ocorrência de um estado desejável– Em algum momento o programa entra em um estado

consistente• Dado um programa concorrente mostrar:

– Não ocorre deadlock/livelock (safety)– Possui uma seção crítica (SC) (safety)– Termina (liveness)– Eventualmente entra em uma SC (liveness)

35Sistemas Distribuídos

Page 36: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Safety [ Introdução ]

• Objetos interagindo em múltiplas Threads normalmente provocam interferência

• Programas concorrentes devem possuir 2 propriedades:– Safety: Nada de mau acontecerá durante a

execução do programa.– Liveness: Algo de bom acontecerá durante a

execução do programa.

Page 37: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Safety [ Introdução ]

• Em geral há mais atenção sobre Safety na engenharia– É melhor que o programa não faça nada a ter um

comportamento aleatório ou até perigoso• Liveness está relacionada ao progresso do

programa• Em alguns casos é melhor obter uma informação

imprecisa a não receber– Sistemas de Suporte a Decisão, Data Warehouse e

Simulação de Trânsito• Melhorar a Liveness pode implicar em reduzir a

Safety

Page 38: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Safety [ Objetos Seguros ]

• Em programa OO, o controle de interferência é implementado de classe a classe

• Objetos/variáveis podem entrar temporariamente em um estado inconsistente

• Um objeto/variável é considerado seguro quando:– Seu estado consistente é sempre consistente– Operações não são realizadas enquanto está em

um estado inconsistente

Page 39: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Safety [ Objetos Seguros ]

• Há 3 estratégias conservadoras para projetar objetos/variáveis seguros:– Imutabilidade: evitar mudanças de estado– Sincronização: garantir acesso exclusivo

dinamicamente– Contenção: garantir acesso exclusivo

estruturalmente

Page 40: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Safety [ Imutabilidade ]

• Variáveis de instância constantes (final em Java)

• Encapsulamento• Não requer sincronização• Classes sem estado (stateless)

– Como não há estado, não há interferência

Page 41: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Safety [ Sincronização ]

• Um Objeto/variável sempre está pronto para sofrer modificações, mesmo quando ainda está no meio do processamento de alguma

• Acesso a estados inconsistentes devem ser evitados:– Conflitos de leitura/escrita: vários lêem enquanto

um escreve– Conflitos de escrita/escrita: vários lêem e

escrevem ao mesmo tempo

Page 42: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Safety [ Sincronização ]

• No contexto de OO, podemos ter:– Sincronização Total

• Objetos totalmente sincronizados. Podem fazer apenas uma operações por vez

– Sincronização Parcial• Parte do objeto é sincronizado. Somente métodos

sincronizados são travados

Page 43: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Safety [ Contenção ]

• Baseia-se na idéia de manter referências únicas para objetos internos isolados dos demais.

• São acessados apenas através de métodos sincronizados do objeto no qual estão contidos, estando, portanto, protegidos.

externo1

interno1

interno2

subinterno1

Page 44: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Safety [ Contenção ]

• Recursos Exclusivos– Garante que somente um objeto por vez é

“proprietário” do recurso exclusivo. Porém, a propriedade de um recurso pode mudar

– Semelhanças com objetos físicos:• Se você tem um, então pode usá-lo• Se você tem um, ninguém mais pode tê-lo• Se você da um para alguém, então deixa de tê-lo• Se você destrói um, ninguém nunca mais o terá

Page 45: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Safety [ Contenção ]

– É preciso definir um protocolo que garanta a exclusividade do recurso

serviço 2serviço 0

serviço 3

serviço 1vizinho

vizinho vizinho

vizinho

null

null

nullRecurso

Page 46: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Liveness [ Introdução ]

• Projetos baseados em combinações de Imutabilidade, Sincronização e Contenção são abordagens simples, rápidas e de fácil entendimento para o desenvolvimento de programas concorrentes OO

• Porém, essas técnicas nem sempre são a melhor solução

• Utilização de Sincronização pode provocar problemas de Liveness (eficiência)

Page 47: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Liveness [ Falhas de Liveness ]

• São tão sérias quanto falhas de Safety• São mais difíceis de identificar e evitar

durante o projeto• Tipos de falhas

– Contenção: uma thread, apesar de estar pronta para executar, não executa porque outra tomou recursos (também conhecida como starvation ou adiamento infinito)

Page 48: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Liveness [ Falhas de Liveness ]

– Dormência: uma thread não pronta falha ao tentar passar para esse estado.

– Deadlock: duas ou mais threads bloqueiam-se em um ciclo vicioso enquanto tentam acessar travas sincronizadas necessárias para continuar suas atividades

– Término prematuro: uma thread é parada ou encerrada prematuramente

Page 49: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Liveness[ Análise de Variáveis de Instância ]

• Através de análise de variáveis e métodos, é possível identificar oportunidades para reduzir a sincronização

• Muitas vezes, a proteção implementada é exagerada

Page 50: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Liveness[ Análise de Variáveis de Instância ]

• Acesso– Métodos de acesso podem deixar de ser

sincronizados para permitir leitura durante a escrita

– Condições para remover a sincronização:• A variável não pode assumir valores ilegais

durante a execução dos métodos• Atribuição atômica

Page 51: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Liveness[ Análise de Variáveis de Instância ]

• Atualização– Métodos de atualização podem abdicar da

sincronização quando satisfaz, além das condições para acesso:

• Valor da variável permanece consistente em todas as possíveis situações (Ex: atributo temperatura sendo atualizado constantemente por múltiplas threads)

• Não requer ações especiais sincronizadas para certos valores assumidos pelas variáveis (Ex: reconstruir uma estrutura de dados após atingir um tamanho)

Page 52: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Sincronização condicional Safety e Liveness

• Como provar que uma propriedade é atendida?– Testes (“provam a presença de erros, mas não a

ausência”)– Formalmente (via asserções etc)

• Notação (similar a linguagem SR):co “bloco de comandos”co “bloco d comandos” // em SR, “// “

oc• “Braços de um comando co” são executados em

paralelo (comando termina quando todos braços terminarem)

52Sistemas Distribuídos

Page 53: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Independência de Processos Concorrentes

• read set: variáveis lidas e não alteradas• write set: variáveis que são alteradas• Independência: dois blocos de comandos

são independentes se o “write set” de cada bloco é disjunto do “read set” e “write set” do outro bloco

• Exemplo: – P1:: x = y +z; P2:: y= 1; z= 2; read_set(P1)= {y, z} write_set(P2)= {y, z}

53Sistemas Distribuídos

Page 54: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Independência de Processos Concorrentes

• race condition: quando programa permite a execução concorrente de blocos de comandos não independentes (ou conflitantes)

• Exemplo: como paralelizar um grep?String line;read a line of input from stdin into line;while (!EOF) {

look for pattern in line; if (pattern is in line)

write line; read next line of input;}

54Sistemas Distribuídos

Page 55: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Exemplo: grep paralelo

• Versão incorreta (com conflitos):String line1;read a line of input from stdin into line1;while (!EOF) { co look for pattern in line1; // read set= line1

if (pattern is in line1) print line1 co read next line into line1; // write set= line1

oc}

55Sistemas Distribuídos

Page 56: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Exemplo: grep paralelo

• Versão correta:String line1,line2;read a line of input from stdin into line1;while (!EOF) { co look for pattern in line1; // read set= line1

if (pattern is in line1) print line1 co read next line into line2; // write set= line2

ocline1 = line2;

}

• Desvantagens: cópia entre linhas e criação de duas threads a cada repetição do laço

56Sistemas Distribuídos

Page 57: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Sincronização

• Execução de programa concorrente: intercalação de “ações atômicas”

• Sincronização: evita “intercalações indesejadas”– Via seções críticas – Via sincronização condicional

• Ação atômica sem condição (ou incondicional):– < S > : executa comandos “S” atomicamente

• Ação atômica com condição (ou condicional):– < await (B); S >: espera ocorrência da condição B,

então executa “S” atomicamente

57Sistemas Distribuídos

Page 58: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Sincronização

• Exemplo: < await(s>0); s=s-1 > < s= s+1 >– Que operações são estas acima?

• Exemplo: < x= x+1; y= y+1; >– “Estados internos” (como x já incrementado e y

não) não são visíveis a outros processos.• Regiões críticas são usadas para tratar

blocos de código conflitantes– No entanto, definir a granularidade de uma seção

crítica não é simples

58Sistemas Distribuídos

Page 59: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Exemplo: Computadores e Leite

59Sistemas Distribuídos

• Processo Aif (SemAviso){

if (SemLeite){

CompraLeite; } DeixaAviso; }

• Processo Bif (Aviso){

if (SemLeite){

CompraLeite; } RemoveAviso; }

• Funciona? Porque?• Somente A deixa aviso e somente se não existe um aviso• Somente B remove um aviso• Portanto:

• Se houver um aviso, B compra leite• Se não houver um aviso, A compra leite• Sendo assim, somente um processo executa a seção crítica

• O que acontece se B sair de férias?• A vai comprar leite uma vez e não poderá comprar mais até que B

retorne

Page 60: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Exemplo: Computadores e Leite

60Sistemas Distribuídos

Processo A Deixa AvisoA; while (AvisoB); if (SemLeite){ Compra Leite; } Remove AvisoA;

Processo B Deixa AvisoB; if (SemAvisoA){ if(SemLeite){ Compra Leite; } }Remove AvisoB;

• Funciona? • Se SemAvisoA, B pode comprar porque A ainda não começou• Se AvisoA, A está comprando ou esperando até que B desista.

B pode desistir• Se SemAvisoB, A pode comprar• Se AvisoB não se sabe:

• Se B comprar, remove AvisoB, fim• Se B não comprar, remove AvisoB, A pode comprar

Solução funciona, mas não é boa Muito complicado. Difícil de

entender e se convencer que está correto

Código de A é diferente de B E se houver mais de 2

processos? Enquanto A está esperando,

está consumindo CPU

Page 61: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Sincronizando Produtores e Consumidores

• Copiar um vetor de inteiros “a” de um processo para outro, usando um buffer compartilhado

• Buffer é uma único inteiro “buf” (compartilhado)

• Sincronização via await implica em uma espera ocupada (“busy wait”)

int buf, p=0, c=0; // p: ints produzidosprocess Producer {//c: ints consumidos int a[n]; while (p<n) { < await (p==c); > // produzido já foi

consumido buf=a[p]; // “produz” p=p+1; } process Consumer { int b[n]; while (c<n) { < await (p>c); > // produzido não foi

consumido b [c]=buf; // “consome” c=c+1; } }

61Sistemas Distribuídos

Page 62: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Políticas de Escalonamento

• Vários processos, com várias ações candidatas a execução. – Como escolher/eleger uma ?

• Por meio de uma política de escalonamento

• Escalonamento incondicionalmente justo (fair): uma ação atômica incondicional candidata a execução é eventualmente executada

62Sistemas Distribuídos

Page 63: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Políticas de Escalonamento

• Escalonamento fortemente justo:– incondicionalmente justo– Em <await B; S>, se B às vezes é falsa e às

vezes é verdade, então a ação não é sempre selecionada quando sua condição é falsa.

• Escalonamento fracamente justo: quando não garante a segunda condição acima.

63Sistemas Distribuídos

Page 64: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Políticas de Escalonamento

• Exemplo:bool continue= true, try= false;co while (continue) { try = true; try= false; }co <await (try) continue= false>;oc

• Se fortemente justo, programa sempre termina

• Se fracamente justo, pode nunca terminar• Na prática, fortemente justo não é

atendido

64Sistemas Distribuídos

Page 65: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Locks e Barreiras

• Como implementar uma seção crítica(SC)?– Por meio de < .... >

• Mas na prática, o que é < .... > ?– Locks (bloqueios)

65Sistemas Distribuídos

Page 66: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Locks e Barreiras

• Problema da Seção Crítica:Process SC[i = 1 to n] { while (true) { entry protocol; critical section; exit protocol; noncritical section; }}

66Sistemas Distribuídos

Page 67: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Locks e Barreiras

• Propriedades:– Exclusão Mútua (safety)– Ausência de deadlocks/livelocks (safety)– Ausência de atrasos desnecessários (safety)– Entrada em tempo finito (liveness)

67Sistemas Distribuídos

Page 68: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Seção Crítica via Locks

• lock: variável booleana que indica se algum processo encontra-se na SC:– lock= true: algum processo está na SC– lock= false: nenhum processo está na SC

• SC com locks:< await (!lock) lock = true; > critical section

lock = false;

68Sistemas Distribuídos

Page 69: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Seção Crítica via Locks

• Como implementar o await acima?– Via uma instrução de hardware

• Test and Set:bool TS(bool lock) { < bool initial = lock; lock = true; return initial; >}

• SC por meio de Test and Set:while (TS(lock)) skip; // CSEntercritical section; // TS(lock) retornou false; lock=true

lock = false; // CSExit

69Sistemas Distribuídos

Page 70: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Seção Crítica via Locks

• Exclusão Mútua:– Dois processos tentam entrar mesmo tempo– Um deles executa TS(lock) primeiro e seta lock para true (entrando

na SC)– Outro, executa TS(lock), retorna true e espera

• Ausência de deadlocks:– Se 2 processos bloqueados, lock=true sempre– Mas para lock ser true, significa que um processo entrou na SC; ele

tem que sair e fazer lock= false

• Ausência de atrasos desnecessários:– Se processo fora da SC, então ele não pode bloquear a entrada do

outro

70Sistemas Distribuídos

Page 71: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Seção Crítica via Locks

• Entrada em tempo finito:– Requer escalonamento fortemente justo– Nesse caso, assegura-se que “processo

atrasado” irá, em algum momento, chamar TS(lock) quando lock=false

• Por fim, <await (B); S> é implementado como:CSEnter; while(!B) { CSExit; delay; CSEnter; }S; CSExit;

71Sistemas Distribuídos

Page 72: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Algoritmo Tie-Breaker

• Solução fair para SC, com dois processos:– “in1” e “in2”: processo está ou não na SC– “last”: último proc. iniciou protocolo entrada

72Sistemas Distribuídos

Page 73: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Algoritmo Tie-Breaker

• Algoritmo:bool in1= false, in2= false; int last= 1;process P1 { while (true) { in1= true; last= 1; while (in2 and last ==1) skip; critical section; in1= false; non-critical section; }}process P2 { while (true) { in2= true; last= 2; while (in1 and last ==2) skip; critical section; in2= false; non-critical section; }}

73Sistemas Distribuídos

Page 74: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Algoritmo Tie-Breaker

• Exclusão Mútua:– Se P1 na SC, (in2==false ou last==2)– Logo, P2 não pode estar também na SC

• Interferência entre processos:– Suponha que in2= false e P1 tente entrar – Antes de P1 entrar, P2 faz in2= true. – P1 entra, mas P2 não consegue pois last==2

74Sistemas Distribuídos

Page 75: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Algoritmo Tie-Breaker

• Fair:– Se P1 e P2 disputando SC (in1= in2= true)– P2 entrou (isto é, P1 setou last por último)– P2 saiu e disputa SC (in2= true; last= 2)– P1 entra (já que last==2)

• Algoritmo Tie-breaker: solução para n processos é mais complexa.

75Sistemas Distribuídos

Page 76: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Algoritmo do Ticket

• Solução fair para SC, com n processos• Algoritmo da “senha” do banco: cliente

chega ao banco, pega uma senha e aguarda ser chamado

• Variáveis:– “number”: núm. da próx. “senha” a distribuir– “next”: núm. do próx. processo a ser atendido– “turn[n]”: armazena senha dos n processos

76Sistemas Distribuídos

Page 77: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Algoritmo do Ticket

• Algoritmo:int number= 1, next=1; int turn[n];process CS[i= 1 to n] { while (true) { < turn[i]= number; number++; > < await (turn[i] == next); > critical section; < next++; > non-critical section; }}

• Depende de uma instrução FA (fetch and add):– FA(x, incr)= < int t= x; x=x+incr; return t; >

• Alternativa: usar “test and set” p/ implementar FA

77Sistemas Distribuídos

Page 78: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Barreiras

• Ponto de sincronização: – todos os processos devem atingir este ponto

para que a execução de quaisquer deles possa prosseguir

• Barreiras usando um contador compartilhado:– Quando processo atinge a barreira, contador

é incrementado– Quando contador igual a “n”, abre-se barreira

78Sistemas Distribuídos

Page 79: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Barreiras

• Exemplo:int count=0......code to implement task i; < count++; > // barreira< await (count==n); >

• Problemas: – como reutilizar a barreira, isto é, como resetar o

contador ? • Contador deve ser resetado antes que um processo tente

incrementá-lo de novo– contenção acesso à memória

• (n-1) processos inspecionando contador, esperando último processo atingir a barreira

79Sistemas Distribuídos

Page 80: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Barreiras com Processo Coordenador

• Evita contenção no acesso à memória– “arrive[i]”: indica se

processo i atingiu barreira

– “continue[i]”:indica pode prosseguir execução

• Quem testa um flag, deve resetá-lo

int arrive[n], continue[n]; // inicializados com zeroprocess Worker[i=1 to n] { while (true) { code to implement task i; arrive[i]=1; // anuncia

chegada < await (continue[i]==1); > // permissão prosseguir continue[i]=0; // reseta

flag } } process Coordinator while (true) { for [i=1 to n] { < await (arrive[i]==1); > // aguarda todos chegarem arrive[i]=0; } for [i=1 to n] continue[i]=1; // avisa podem

prosseguir }

80Sistemas Distribuídos

Page 81: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Semáforos

• Implementação de SC não é trivial• Logo, necessita-se de mecanismos de

sincronização de mais alto nível, tais como– < S > e < await (B); S > (linguagem SR)– Semáforos e monitores

• Semáforos (Dijkstra, 1968): variável inteira compartilhada entre processos.

• Operações sobre semáforos:– sem s; (inicialização)– P(s): < await (s>0) s = s-1; > (ou wait) – V(s): < s = s+1; > (ou signal)

81Sistemas Distribuídos

Page 82: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Semáforos

• Exemplo 1: Implementação de Seção Crítica

sem livre=1; // livre= 1: SC livreprocess CS[i=1 to n] { while (true){ wait(livre); critical section; // livre= 0: processo na SC signal(livre); noncritical section; } }

82Sistemas Distribuídos

Page 83: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Semáforos

• Exemplo 2: Erros na utilização de semáforos:– wait(livre); CS; wait(livre); (deadlock)

– signal(livre); CS; wait(livre); (sem exclusão)

• Semáforo binário: valor é sempre 0 ou 1• Semáforo sinalizador: inicializado com zero

– Esperando um evento: wait(s)– Sinalizando evento: signal(s)

83Sistemas Distribuídos

Page 84: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Semáforos

• Exemplo 3: Barreiras (semáforo sinalizador)sem arrive1= 0, arrive2= 0;process Worker1 { “executa task1”; signal(arrive1); wait(arrive2); ............ // assegura-se que task1 e task2 executadas}

process Worker2 { “executa task2”; signal(arrive2); wait(arrive1); ........... // assegura-se que task1 e task2 executadas}

84Sistemas Distribuídos

Page 85: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Produtor/Consumidor

• M prod., N consumidores e buffer com um inteiro

• Semáforos:– empty: usado para sinalizar

que buffer vazio– full: usado para sinalizar

que buffer cheio

• Semáforos particionados (split): um processo executa P(s);...;V(r) e outro processo P(r);...;V(s)

int buf; sem empty=1, full=0; // inicialmente buffer vazio process Producer[i=1 to M] { while(true) { “produce data“ P(empty); // espera buffer vazio para produzir

buf=data; V(full); // após produzir, sinaliza qbuffer está cheio }}process Consumer[j=1 to N] { while(true) { P(full); // espera buffer cheio para consumir result=buf; V(empty); // após consumir, sinaliza buffer vazio }}

85Sistemas Distribuídos

Page 86: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Produtor/Consumidor com Buffer de Tamanho n

• Variáveis:– rear: índice onde será inserido próximo valor– front: índice de onde será lido próximo valor

• Valores armazenados no buffer: iniciam em front e terminam em rear-1, de forma circular

• Possível intercalar “produtores” com “consumidores” (em posições diferentes)

• Intercalações impossíveis: “produtores com produtores”, “consumidores com consumidores”

86Sistemas Distribuídos

Page 87: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Produtor/Consumidor com Buffer de Tamanho n

• Semáforos para criar SC: mutexP e mutexC– Produtor: P(mutexP); “produz”; V(mutexP)– Consum.: P(mutexC); “consome”; V(mutexC)

• Semáforos para sinalizar mudanças no buffer:– empty: armazena número de posições vazias– full: armazena número de posições ocupadas– empty+full == n (por construção do algoritmo)

• Antes produzir, deve existir slot vazio: P(empty)• Após produzir, um slot ficou ocupado: V(full)• Antes consumir, deve existir slot ocupado: P(full)• Após consumir, um slot ficou vazio: V(empty)

87Sistemas Distribuídos

Page 88: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Produtor/Consumidor com Buffer de Tamanho n

int buf[n]; int front=0, rear=0;sem empty=n, full=0; sem mutexP=1, mutexC=1 # for mutual exclusionprocess Producer[i=1 to M] { # M producers while(true) { “produce data“ P(empty); # block if buffer full - empty is 0 P(mutexP); # block multiple producers to access buffer buf[rear]=data; rear=(rear+1)%n; V(mutexP); # leave critical section V(full); # increment full counter - split semaphore }}

88Sistemas Distribuídos

Page 89: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Produtor/Consumidor com Buffer de Tamanho n

process Consumer[j=1 to N] { # N consumers while(true) { P(full); #block if buffer empty - full is 0 P(mutexC); # block multiple consumers to access

# buffer result=buf[front]; front=(front+1)%n; V(mutexC); #leave critical section V(empty); # increment empty counter-split

# semaphore “consume result” }}

89Sistemas Distribuídos

Page 90: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Jantar dos Filósofos

• Filósofos pensam, comem, pensam, comem, ...

• Para comer, precisam de dois garfos• Existem apenas cinco garfos na mesa

90Sistemas Distribuídos

Page 91: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Jantar dos Filósofos• O problema dos filósofos é um exemplo clássico da Programação Concorrente. Tem

por objetivo demonstrar a alocação de recursos quando temos processos que concorrem pela alocação dos mesmos, ou seja, os recursos são escassos

• A implementação proposta apresenta cinco filósofos e cinco garfos. A idéia central deste problema é que dado os FILÓSOFOS e os GARFOS em um jantar, cada filósofo necessita de dois garfos para comer. Os filósofos podem estar em três estados: PENSANDO, FAMINTO ou COMENDO. Se um dos filósofos está no estado PENSANDO e quer passar para o estado COMENDO, ele tenta pegar dois garfos. Se ele não consegue pegar os dois garfos, passa para o estado FAMINTO. Se consegue pegar dois garfos ele passa para o estado COMENDO. Enquanto no estado faminto, o filósofo permanece tentando pegar os garfos, ou seja, fica esperando a liberação de garfos.

• Como é de conhecimento, caso não exista uma ordem para pegar os garfos, pode ocorrer deadlocks ou espera eterna. Para tanto adotamos a seguinte solução: quando um filósofo quer comer, ele toma um garfo do filósofo a sua direita, se este filósofo não o estiver usando. Assim sendo, os métodos que implementam o ato de pegar e liberar os garfos são sincronizados, ou seja, somente um filósofo entra no corpo do método por vez

91Sistemas Distribuídos

Page 92: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Jantar dos Filósofos

• Solução: vetor de semáforos representa garfos– sem fork[5]= {1,1,1,1,1} # garfos estão livres

• Pegar garfo i: P(fork[i]) – < await fork[i] > 0; fork[i]= fork[i] -1; >

• Liberar garfo i: V(fork[i]);– < fork[i]= fork[i]+1; >

92Sistemas Distribuídos

Page 93: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Jantar dos Filósofos

• Filósofos pegam o garfo da direita e, logo em seguida, o garfo da esquerda

P(fork[i]); P(fork[(i+1)mod 5 ] );comerV(fork[i]); V(fork[(i+1) mod 5 ]);

93Sistemas Distribuídos

Page 94: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Jantar dos Filósofos

• Deadlock: filósofos morrem de fome quando cada um pega o garfo à sua esquerda e se recusa a liberá-lo

• Deadlock: é um ciclo de espera – P1 espera por recurso com P2; – P2 espera por recurso com P3; – .....– Pn espera por recurso com P1

94Sistemas Distribuídos

Page 95: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Jantar dos Filósofos

• Solução: quebrar o ciclo acima– Filósofo 4 pega primeiro o garfo à sua esquerda

(isto é, garfo à direita do Filósofo 3)– Assim, Filósofo 3 e 4 disputam este garfo: quem

ganhar, come (e evita-se o deadlock)• Outra solução: limitar a quatro o número de

filósofos que podem comer simultaneamente– sem room= 4;– Ao ficar com fome: P(room)– Após comer: V(room)

95Sistemas Distribuídos

Page 96: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Leitores e Escritores

• Dois tipos de processos -- leitores e escritores -- compartilham um banco de dados:– Escritores devem ter acesso exclusivo ao BD– Vários leitores podem acessar juntos o BD

96Sistemas Distribuídos

Page 97: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Leitores e Escritores

• Escritor: acessa BD em uma SC (semáforo rw=1)– P(rw); “write database”; V(rw)

• Leitor:– nr: número de leitores ativos (acessando BD)– Ao inciar leitura: incrementar nr – Ao terminar leitura: decrementar nr– Se primeiro leitor a usar (nr == 1): P(rw)– Se último leitor a usar (nr == 0): V(rw)

97Sistemas Distribuídos

Page 98: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Leitores e Escritores

• Primeira versão do leitor:process Reader[i= 1 to M] {

while(true) {< nr++; if (nr == 1) then P(rw); >"read database"< nr--; if (nr == 0) then V(rw); >

}}

• Semáforo mutexR: exclusão mútua no acesso à variável nr

98Sistemas Distribuídos

Page 99: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Leitores e Escritores

int nr= 0; # number of active readersint rw= 1; # lock for reader/writer

exclusionsem mutexR= 1;# lock for reader access to

nrprocess Reader[i= 1 to M] { while(true) { P(mutexR); nr++; if (nr == 1) then P(rw);

# if first, get lock V(mutexR) "read database" P(mutexR) nr--; if (nr == 0) then V(rw);

# if last, release lock V(mutexR) }}

process Writer[j= 1 to n] { while (true) { .... P(rw); "write the database”; V(rw); }}

• Esta solução não é fair, pois privilegia leitores

• Se um leitor usando; e se um leitor e um escritor desejarem usar, então leitor vai usar

• Um fluxo de leitores atrasa um escritor

99Sistemas Distribuídos

Page 100: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Monitores

• Mecanismo de sincronização de mais alto nível, quando comparado com semáforos

• Adotado em várias linguagens, como em Java

• Monitor = variáveis + procedimentos (objeto)• Monitor: mecanismo de abstração de dados• Suporta automaticamente exclusão mútua

– em um dado instante, apenas um processo pode executar procedimentos de um monitor

– Logo, compilador (e não o programador) fica responsável por assegurar exclusão mútua

100Sistemas Distribuídos

Page 101: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Monitores

• Sintaxe:monitor <name> { <declaração de variáveis> <procedimentos>}

• Chamando procedimento de um monitor:call <name>.<opname> ( <argumentos> )

• Variáveis de um monitor são sempre privadas

101Sistemas Distribuídos

Page 102: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Monitores

• Sincronização condicional (await) em monitores: implementada usando “variáveis condicionais”– Sintaxe: cond cv; // cv é uma var. condicional

• Valor de uma var. condicional: fila de processos• Manipulando variáveis condicionais:

– empty(cv): fila de cv vazia ?– wait(cv): processo se “auto-enfilera” na fila de cv e

libera o monitor– signal(cv): “acorda” o processo na 1a posição da fila

associada a cv

102Sistemas Distribuídos

Page 103: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Monitores

• Existem duas semânticas para um signal:– Signal and Continue (SC): quem emitiu o

signal continua executando (processo sinalizado executa mais tarde)

– Signal and wait (SW): quem emitiu o signal “libera” o monitor (processo sinalizado então inicia execução)

103Sistemas Distribuídos

Page 104: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Implementando Semáforos com Monitores

monitor semáforo { int s= 0; // valor do semáforo cond pos; // fila de processos esperando procedure P() { while (s == 0) wait(pos); s= s - 1; } procedure V() { s= s + 1; signal(pos); }

}

104Sistemas Distribuídos

Page 105: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Implementando Produtor Consumidor com Monitores

monitor Buffer { int buf[n]; # buffer int primeiro=0, #primeira posição ocupada buf ultimo=0; # primeira posição livre em buf cont=0; # número de slots ocupados em bh cond full,#produtores esperando pq buf cheio empty;#consumidores esperando pq buf vazio

105Sistemas Distribuídos

Page 106: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Implementando Produtor Consumidor com Monitores

procedure inserir (int dado) { while (cont==n) wait(full);

# enquanto buf cheio, esperar buf[ultimo]=dado; ultimo=(ultimo+1) % n; cont++; signal (empty);

# acorda consumidor esperando }

106Sistemas Distribuídos

Page 107: Sistemas Distribuídos Aula 04 – Programação Multithread/Paralela Prof. Hélio de Sousa Lima Filho (helio.filho@gmail.com)helio.filho@gmail.com.

Implementando Produtor Consumidor com Monitores

procedure retirar (int &dado) { while (cont==0) wait (empty); # enquanto buf vazio, espera dado=buf[primeiro]; primeiro=(primeiro+1) % n; cont--; signal(full); # acorda produtor esperando } }

107Sistemas Distribuídos