Programa cão Paralela

Propaganda
DCC 837
Programac~ao Paralela
Osvaldo Carvalho - DCC/UFMG
2o Semestre - 1998
(U ltima Modicac~ao: 30 de Novembro de 1998)
2
Indice
1 Apresentac~ao do Curso
1.1 Motivac~ao . . . . .
1.1.1 Objetivos .
1.2 Informac~oes . . . .
1.2.1 Ementa . .
1.2.2 Calendario
1.2.3 Avaliac~ao .
1.2.4 Bibliograa
1.2.5 LINKS . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
I Express~ao e Implementac~ao do Paralelismo
7
7
9
10
11
12
12
13
13
15
2 Introduc~ao a Programac~ao Paralela Assncrona
17
2.1 Paralelismo Programac~ao Paralela . . . . . . . . . . . . . . . . 17
2.1.1 Modo de execuc~ao Modelo de Programac~ao . . . . . . . 18
2.2 Programaca~o Paralela Assncrona . . . . .
2.2.1 Porque PP assncrona? . . . . . . .
2.2.2 Express~ao do Paralelismo . . . . .
2.2.3 Exemplos de Programas Paralelos
2.3 Sem^antica de Programas Paralelos . . . .
2.3.1 Conitos . . . . . . . . . . . . . .
2.3.2 Sem^antica Operacional . . . . . . .
2.3.3 Comandos Conitantes . . . . . .
3
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
19
19
20
21
23
23
25
26
INDICE
4
2.4
2.5
2.6
2.7
2.3.4 Resumo . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Regi~oes Crticas . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.4.1 Exclus~ao Mutua . . . . . . . . . . . . . . . . . . . . . . .
2.4.2 Liberac~ao do Processador . . . . . . . . . . . . . . . . . .
2.4.3 Propriedades de programas paralelos e o problema dos
Leitores e Escritores . . . . . . . . . . . . . . . . . . . . .
2.4.4 Imposic~ao de Polticas de Escalonamento: Programac~ao
de um Servidor de Impressora . . . . . . . . . . . . . . . .
2.4.5 Conclus~oes . . . . . . . . . . . . . . . . . . . . . . . . . .
Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Respostas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.6.1 Quicksort Paralelo . . . . . . . . . . . . . . . . . . . . . .
2.6.2 Comparac~ao e Troca em Paralelo . . . . . . . . . . . . . .
2.6.3 Transac~oes . . . . . . . . . . . . . . . . . . . . . . . . . .
2.6.4 A rvore B . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.6.5 Pool de Recursos Id^enticos . . . . . . . . . . . . . . . . .
1a Prova . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.7.1 1a Quest~ao . . . . . . . . . . . . . . . . . . . . . . . . . .
2.7.2 2a Quest~ao . . . . . . . . . . . . . . . . . . . . . . . . . .
2.7.3 3a Quest~ao . . . . . . . . . . . . . . . . . . . . . . . . . .
2.7.4 4a Quest~ao . . . . . . . . . . . . . . . . . . . . . . . . . .
2.7.5 5a Quest~ao . . . . . . . . . . . . . . . . . . . . . . . . . .
3 Nucleos de Multiprogramac~ao
3.0.1
3.0.2
3.0.3
3.0.4
3.0.5
3.0.6
Interrupc~oes em PCs . . . . . .
Co-rotinas . . . . . . . . . . . .
Multiplexac~ao do Processador .
Chaves e Camas . . . . . . . .
Resumo e Conclus~oes . . . . .
Exerccios . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4 Introduc~ao a Programac~ao Paralela em Java
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
27
28
29
32
33
39
43
44
46
46
47
47
48
49
52
52
52
52
53
53
55
55
57
58
61
63
63
65
4.1 Introduc~ao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
INDICE
4.2
4.3
4.4
4.5
4.6
5
4.1.1 O Fen^omeno Java . . . . . .
4.1.2 Hello World . . . . . . . . . .
4.1.3 Java n~ao tem pointers . . . .
4.1.4 Uma aplicac~ao real: Prj2tex .
Applets . . . . . . . . . . . . . . . .
4.2.1 Vis~ao Geral . . . . . . . . . .
Eventos . . . . . . . . . . . . . . . .
Threads . . . . . . . . . . . . . . . .
Conclus~oes . . . . . . . . . . . . . .
1o Trabalho Pratico . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5 Outras Linguagens e Notaco~es para Programac~ao Paralela
5.1 Especicaca~o de Execuc~ao em Paralelo . . .
5.2 Sincronizaca~o com Memoria Compartilhada
5.2.1 Acessos Indivisveis a Memoria . . .
5.2.2 Semaforos . . . . . . . . . . . . . . .
5.2.3 Monitores . . . . . . . . . . . . . . .
5.2.4 \Path Expressions" { 1 . . . . . . .
5.2.5 Mensagens . . . . . . . . . . . . . .
5.2.6 Conclus~oes . . . . . . . . . . . . . .
5.3 CSP { Communicating Sequential Processes
5.3.1 Conceitos e Notac~oes . . . . . . . . .
5.3.2 Exemplos de Uso . . . . . . . . . . .
5.3.3 Notas . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
65
67
67
67
68
68
70
71
76
77
79
79
80
80
81
86
87
88
89
89
90
98
103
II Formulac~ao e Prova de Propriedades de Programas
Paralelos
105
6 Modelos Formais para Programas Paralelos
107
6.0.1 O Buer Compartilhado . . . . . . . . . . . . . . . . . . . 108
6.0.2 Invariantes . . . . . . . . . . . . . . . . . . . . . . . . . . 111
6.0.3 Variaveis Auxiliares . . . . . . . . . . . . . . . . . . . . . 113
INDICE
6
6.0.4 Atingibilidade: o mais forte invariante
6.1 Modelos Formais: Progresso . . . . . . . . .
6.1.1 Tecnicas de Prova de P leads;to Q . .
6.1.2 Produtor e Consumidor . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
115
116
118
119
7 Transac~oes e o Protocolo 2-fases
121
III Programac~ao Distribuda
129
8 Programac~ao Distribuda
131
7.0.1 Travamentos . . . . . . . . . . . . . . . . . . . . . . . . . 122
7.1 Conclus~oes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
8.1 The Drinking Philosophers Problem . . . . . . . . .
8.2 Exclus~ao Mutua Distribuda . . . . . . . . . . . . . .
8.2.1 Relogios Logicos e Timestamps . . . . . . . .
8.2.2 Algoritmo de Ricart e Agrawala (1981) . . .
8.2.3 Carvalho e Roucairol (1983) { 1 . . . . . . . .
8.2.4 O Algoritmo de Maekawa (1985) . . . . . . .
8.2.5 Algoritmo de Carvalho e Campos (1991) { 1 .
8.2.6 O Algoritmo de Naimi-Trehel . . . . . . . .
8.3 2o Trabalho Pratico . . . . . . . . . . . . . . . . . .
8.3.1 Voyager . . . . . . . . . . . . . . . . . . . . .
IV Balanco e Conclus~oes
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
132
139
140
143
145
147
152
157
170
170
173
Cap
tulo 1
Apresentac~ao do Curso
Programac~ao Paralela
1.1 Motivac~ao
Alguns dos primeiros computadores tinham uma instruc~ao l^e cart~ao , que
comandava diretamente a leitora de cart~oes, enviando instruc~oes e recebendo
dados, ate a leitura completa do cart~ao, quanto o uxo normal de execuc~ao
de instruc~oes da CPU era retomado. A leitura de um cart~ao envolvia a movimentac~ao mec^anica do cart~ao, e era intrinsecamente lenta, tomando um tempo
em que a CPU poderia executar alguns milhares de instruc~oes. CPUs eram
muito caras, da ordem de milh~oes de dolares, e todo esforco para um melhor
aproveitamento de seus recursos era justicavel.
Surgiu ent~ao a ideia de leitura antecipada1 dos cart~oes. Os 80 bytes lidos de um
cart~ao seriam colocados em uma area de memoria, chamada buer . Enquanto
a leitora estivesse operando, o programa do usuario continuaria fazendo seus
calculos, usando a CPU. Quando o programa do usuario quisesse ler um cart~ao,
sua imagem seria obtida diretamente da memoria, numa operac~ao rapida. Uma
ideia simples e boa, que entretanto colocava novos problemas:
o modelo de programac~ao para o usuario n~ao deveria ser altera-
do. O programador comum poderia continuar a pensar que o comando
read(cardReader, cardImage) acionava a leitora, e lia efetivamente os mesmos cart~oes, na mesma ordem em que estavam colocados no escaninho de
entrada;
era necessario um mecanismo para a leitora avisar do termino da leitura
de um cart~ao, de onde surgiu a interrupc~ao
1
http://www.dcc.ufmg.br/~vado/java/CardReaderApplet/CardReaderApplet.html
7
~ DO CURSO
CAPITULO 1. APRESENTACAO
8
o programa do usuario deveria esperar quando o buer estivesse vazio, e
a leitora deveria esperar quando o buer estivesse cheio
A Disciplina Programac~ao Paralela
Todas estas ideias surgiram na decada de 50, quando tecnicas ad-hoc de programac~ao foram empregadas para resolver os problemas de sincronizac~ao gerados
pela leitura antecipada. A CPU cou dividida em duas tarefas: uma executava o programa do usuario, e a outra era o driver da leitora de cart~oes. As
interrupc~oes eram usadas para alternar a tarefa em execuc~ao pela CPU.
A programac~ao paralela , ou programac~ao concorrente , e a disciplina
que veio a tratar de forma sistematica as tecnicas de programac~ao associadas
a problemas como a leitura antecipada. O artigo Cooperating Sequential Processes [Dijkstra, 1965a], publicado por Dijkstra em 1965, pode ser considerado
um marco para a area. Conceitos como processos, independ^encia de velocidades relativas, regi~oes crticas, exclus~ao mutua, semaforos foram ali introduzidos
{ ao menos para a academia, pois varios dentre eles ja eram de uso corrente
na industria. Hoje em dia s~ao incontaveis as aplicac~oes e areas de pesquisa
associadas a programac~ao paralela.
Leitores e Escritores
Esta applet dispara 12 processos (threads ) paralelos, sujeitos a um tipo de sincronizac~ao que ilustra os problemas estudados neste curso. Seis processos s~ao
\leitores", e podem ler simultaneamente uma certa estrutura de dados. A vida
de um processo leitor e cclica:
1. ele \pensa", isto e, faz qualquer atividade n~ao relacionada com esta sincronizac~ao,
2. ca \faminto", isto e, faz uma requisic~ao de leitura, e
3. l^e efetivamente, ao receber uma autorizac~ao de leitura, apos o que volta a
pensar.
Seis outros processos s~ao \escritores", com ciclos de vida analogos. Quando um
escritor escreve, nenhum outro pode escrever, e nenhum leitor pode ler. Aperte
Start, e veja o que acontece.
Nosso curso se preocupa com a construc~ao de programas como este. Preocupase tambem com a formulac~ao e prova de propriedades destes programas. Um
tipo de propriedade e expresso pela obedi^encia a restric~ao de sincronizac~ao que
falamos. Outras propriedades podem ser satisfeitas ou n~ao, como por exemplo:
toda operac~ao de escrita e bem sucedida, ou e possvel que um escritor permaneca esperando por um tempo indeterminado? Experimente: aperte Stop,
~
1.1. MOTIVACAO
9
modique os valores de entrada que determinam os tempos medios de leitura e
escrita, assim como os tempos medios em que um processo ca \pensando", e
aperte Start outra vez. Voc^e vera facilmente que se o tempo em que os leitores
pensam for reduzido, pode ser que um escritor n~ao consiga nunca realizar sua
escrita.
Objeto do Curso
Programac~ao Paralela Assncrona
Aplicac~oes:
animac~oes na Web
sistemas operacionais
protocolos
sistemas de tempo real
sistemas reativos como centrais telef^onicas
interfaces gracas
bancos de dados
arquiteturas cliente/servidor
aplicac~oes numericas
...
1.1.1 Objetivos
O objetivo deste curso e o estudo de conceitos, metodos e algoritmos apropriados para a construc~ao e a analise de programas paralelos e distribuidos.
Ao termino do curso o aluno tera acumulado um pequeno arsenal de so-
luc~oes classicas, estara apto a desenvolver e analisar programas paralelos,
e tambem a ler e analisar artigos de pesquisa na area.
O que este curso n~ao e
um curso sobre o uso ecaz de maquinas paralelas (veja o curso de Ci^encia
Computacional2)
2
http://www.dcc.ufmg.br/~kitajima/FCC98
~ DO CURSO
CAPITULO 1. APRESENTACAO
10
um curso sobre analise de complexidade de algoritmos paralelos, utilizando
PRAM ou outros modelos similares (veja o curso de Estruturas de Dados)
um curso de algoritmos numericos paralelos
mesmo se os princpios aqui estudados s~ao de alguma utilidade para estas areas.
Pre-Requisitos
Espera-se que o aluno tenha maturidade em programac~ao e em estruturas
de dados. Java sera a linguagem adotada, mas orientaca~o a objetos n~ao e
explorada a n~ao ser no inevitavel.
Comentarios
Programac~ao paralela se aprende como a programac~ao sequencial, atraves do
estudo de algoritmos e linguagens;
Os programas paralelos que vamos estudar reagem a eventos assncronos ,
como a chegada de um pacote pela rede, ou o apertar de uma tecla;
(Um outro nome para este curso seria \Programac~ao de Sistemas Reativos" )
Isto introduz caractersticas de n~ao-determinismo , e de difcil reproduc~ao
de uma execuc~ao;
Estas diculdades tornam necessario um formalismo mais rigoroso para o
tratamento de programas paralelos
1.2 Informac~oes
Segundas e quartas, de 16:35 as 18:20
Sala 2077 do ICEx
Professor: Osvaldo Carvalho
{ e-mail: [email protected]
{ www: http://www.dcc.ufmg.br/~vado4
{ Sala 4018
{ Telefone 499 5860
3
4
mailto:[email protected]
http://www.dcc.ufmg.br/~vado
~
1.2. INFORMACOES
11
{ As transpar^encias do curso se encontram disponveis na rede, mas o
aluno deve sempre se lembrar de que est~ao em construc~ao , com
modicac~oes introduzidas com o avanco do curso.
{ O mesmo vale para o arquivo postscript; use o ghostview para imprimir apenas as paginas das proximas uma ou duas aulas.
{ Para ver as applets, e necessario usar um browser compatvel o JDK
(Java Development Kit) 1.1.5 , como o Netscape Communicator
do DCC/UFMG.
1.2.1 Ementa
1. Express~ao e Implementac~ao do Paralelismo [Andrews and Schneider, 1983],[Bal et al., 1989].
Express~ao do paralelismo, conitos no acesso a dados compartilhados,
ferramentas de sincronizac~ao e sua implementac~ao;
2. Formulac~ao e Prova de Propriedades de Programas Paralelos [Keller, 1976],
[Owick and Gries, 1976], [Shankar, 1993], [Eswaran et al., 1976],[Kohler, 1981],[Gray and Reuter, 1993a].
Modelos de programas paralelos; metodos formais para a express~ao
e prova de propriedades como \toda requisic~ao sera satisfeita num
tempo nito", ou \nunca teremos dois clientes utilizando um certo
recurso simultaneamente"
3. Programac~ao Distribuda [Lamport, 1978],[Ricart and Agrawala, 1981], [Carvalho and Roucairol, 1983],
[Chandy and Misra, 1984], [de Aguiar Campos and Carvalho, 1988], [Barbara and Garcia-Molina, 1986].
Programaca~o paralela com interac~ao entre processos restrita a troca
de mensagens, que sofrem atrasos de transmiss~ao, impossibilitando
consultas ao estado global.
Seminarios:
Ambientes de programac~ao paralela
Coer^encia de cache
Sistemas de transac~oes
Arquiteturas cliente/servidor
Programac~ao por Agentes
Hardware de Sincronizaca~o
~ DO CURSO
CAPITULO 1. APRESENTACAO
12
1.2.2 Calendario
Aula Data
1
31/08/98
02/09/98
07/09/98
2
09/09/98
3
14/09/98
16/09/98
4
21/09/98
5
23/09/98
6
28/09/98
7
30/09/98
8
05/10/98
9
07/10/98
10
12/10/98
11
14/10/98
12
19/10/98
13
21/10/98
14
26/10/98
15
28/10/98
02/11/98
16
04/11/98
17
09/11/98
18
11/11/98
19
16/11/98
20
18/11/98
21
23/11/98
22
25/11/98
23
30/11/98
24
02/12/98
25
07/12/98
26
09/12/98
27
14/12/98
28
16/12/98
29
21/12/98
30
23/12/98
Dia
2a
4a
2a
4a
2a
4a
2a
4a
2a
4a
2a
4a
2a
4a
2a
4a
2a
4a
2a
4a
2a
4a
2a
4a
2a
4a
2a
4a
2a
4a
2a
4a
2a
4a
Assunto
Apresentac~ao
aula adiada
Feriado
Programac~ao Paralela Assncrona
Sem^antica de Programas Paralelos
aula adiada
Regi~oes Crticas
Exemplos
Exerccios
1a Prova
1a Prova - Gabarito
Java - Introduc~ao
Java - GUI, Applets
Java - Threads
Nucleos de Multiprogramac~ao
Linguagens e Construc~oes
CSP
Exerccios
Feriado
Modelos Formais para Programas Paralelos
Invariantes
Progresso
Transac~oes e o Protocolo Duas-Fases
O Jantar dos Filosofos
Exclus~ao Mutua - Lamport, RA, CR
Exclus~ao Mutua - Maekawa
Exclus~ao Mutua - Naimi Trehel
Exerccios
Exerccios
2a Prova
2a Prova - Gabarito
Seminarios
Seminarios
Balanco e Conclus~oes
1.2.3 Avaliac~ao
A avaliac~ao dos alunos sera feita por provas, trabalhos praticos e uma monograa. As provas s~ao longas, e os alunos ter~ao 24 horas para faz^e-las. Os alunos
poder~ao propor outros temas para as monograas, alem dos sugeridos na ementa. Toda monograa sera objeto de uma apresentac~ao a ser feita pelo aluno no
m do curso. Para cada seminario o aluno devera elaborar uma monograa no
~
1.2. INFORMACOES
13
formato de um artigo a ser submetido para um congresso.
Duas provas
50
Dois trabalhos praticos 30
Seminario
20
1.2.4 Bibliograa
O curso sera baseado em notas de aula e artigos.
1.2.5 LINKS
Latex e Latex2html
Um Exemplo Simples do Uso de Latex e Latex2html
Tex, Uppsala University5
Advanced LaTeX6
LaTeXe help 1.67
The LATEX2HTML Translator8
All About LaTeX2HTML9
Java
Pagina do Marco Aurelio10
Tutorial de Java11 (local)
Ambiente Java no DCC-UFMG12
Tutorial sobre threads em Java13
ObjectSpace: excelentes bibliotecas Java14
http://www.csd.uu.se/documentation/tex/
http://www-h.eng.cam.ac.uk/help/tpl/textprocessing/latex advanced/latex advan
ced.html
7 http://www.loria.fr/services/tex/general/latex2e.html
8 http://www-math.mpce.mq.edu.au/texdev/LaTeX2HTML/docs/manual/
9 http://cbl.leeds.ac.uk/ nikos/tex2html/doc/latex2html/latex2html.html
10 http://hematita.dcc.ufmg.br/~corelio/java.html
11 http://www.dcc.ufmg.br/javadoc
12 http://www.dcc.ufmg.br/~crc/servicos/java.html
13 http://www.magelang.com/thread course/
14 http://www.objectspace.com
5
6
14
~ DO CURSO
CAPITULO 1. APRESENTACAO
Links Java15
Curso Programac~ao Concorrente, McGill16
The mother of all Java FAQ lists17
Bibliograa
Colec~ao de bibliograas em Ci^encia da Computac~ao18
Biblioteca digital da ACM19 Biblioteca digital da IEEE20
Book Pool21
Amazon Books22
Outros
Algoritmos distribudos23
Pagina ocial PVM24
CENAPAD-MG/CO25
15
16
17
18
19
20
21
22
23
24
25
http://home.intranet.org/~mouse/links/java.html
http://www.openface.ca/~skow/623/schedule.html
http://www-net.com/java/faq
http://liinwww.ira.uka.de/bibliography/index.html#search
http://www.acm.org/dl
http://www.computer.org/epub/
http://www.bookpool.com
http://www.amazon.com
http://www.mpi-sb.mpg.de/%7Etsigas/DISAS/
http://www.epm.ornl.gov/pvm/pvm home.html
http://www.cenapad.ufmg.br
Parte I
Express~ao e Implementac~ao
do Paralelismo
15
Cap
tulo 2
Introduc~ao a Programac~ao
Paralela Assncrona
Motivac~ao :
uso simult^aneo de recursos (ex.: CPU e leitora de cart~oes)
acelerac~ao de programas (ex.: resoluc~ao de um sistema de equac~oes
num multiprocessador)
simplicac~ao do modelo de programac~ao: uma maquina paralela assncrona
e mais simples de se programar que uma maquina sequencial com interrupc~oes
interatividade com o usuario (ex.: interfaces gracas)
e desaante!
2.1 Paralelismo Programac~ao Paralela
Encontramos paralelismo em todos os lugares:
{ CPU e perifericos
{ Pipelines
{ Maquinas vetoriais
{ Canais de E/S
{ Multiprocessadores
{ Redes
{ e e bom lembrar que todos os computadores do mundo que encontramse ligados neste instante est~ao funcionando em paralelo!
17
~ A PROGRAMACAO
~ PARALELA ASSINCRONA
18CAPITULO 2. INTRODUCAO
2.1.1 Modo de execuc~ao Modelo de Programac~ao
Um problema central da programac~ao paralela e a implementac~ao de uma
camada de abstrac~ao
isto deve ser feito utilizando recursos de uma maquina dada para construir
uma outra maquina;
esta outra maquina oferece um modelo de programac~ao mais adequado
para seus utilizadores
Hardware de mono-processadores
a maquina de base e formada de componentes de hardware : portas,
ULAs, memorias, etc.;
e projetado de forma a explorar o paralelismo (geralmente) sncrono inerente aos circuitos eletr^onicos;
oferece uma maquina cujo modelo de programaca~o e sequencial com
interrupc~oes .
Nucleos de multiprogramac~ao
a maquina de base e sequencial com interrupco~es (oferecida pelo
hardware de um mono-processador)
e projetado de forma a esconder as interrupc~oes
oferece um modelo de programac~ao paralelo assncrono , com primitivas para coordenaca~o de processos
(este mesmo modelo pode ser construdo a partir de um multiprocessador)
Sistema operacional tradicional
a maquina de base e paralela e assncrona (oferecida por um nucleo
de multiprogramac~ao)
e projetado de forma a explorar o paralelismo no uso dos recursos de
hardware
oferece um modelo de programac~ao sequencial sem interrupco~es
~ PARALELA ASSINCRONA
2.2. PROGRAMACAO
19
Conclus~oes
Paralelismo 6= Programac~ao Paralela
Um programa sequencial pode ser executado em paralelo
Um programa paralelo pode ser executado sequencialmente
Modo de execuc~ao e modelo de programac~ao s~ao conceitos distintos!
2.2 Programac~ao Paralela Assncrona
Na programac~ao paralela assncrona,
um programa e um conjunto de processos sequenciais
( conceito abstrato de processo n~ao deve ser confundido com o de processo
de um sistema operacional como o Unix)
a correc~ao de um programa n~ao deve depender das velocidades relativas
dos processos
primitivas de sincronizac~ao controlam as interac~oes entre os processos
Pontos estudados neste curso:
Como programar uma maquina paralela assncrona?
Como implementar uma maquina paralela assncrona?
2.2.1 Porque PP assncrona?
um computador deve reagir a estmulos cujo instante de chegada e im-
previsvel, como a chegada de um pacote pela rede, ou o apertar de uma
tecla.
a troca de um componente por outro de desempenho superior ocorre todos
os dias
se podemos ter uma soluca~o mais geral, porque n~ao adota-la?
~ A PROGRAMACAO
~ PARALELA ASSINCRONA
20CAPITULO 2. INTRODUCAO
2.2.2 Express~ao do Paralelismo
Linguagens como C ou Pascal n~ao possuem comandos para expressar exe-
cuc~ao em paralelo (existem muitas bibliotecas que oferecem rotinas para
isto)
O Unix oferece o comando
fork para cria
c~ao de processos pesados e
uma biblioteca para tratamento de processos leves
Java oferece classes para criac~ao e execuca~o de processos leves, ou threads
Existem inumeras propostas comerciais e acad^emicas
Vamos comecar por uma proposta acad^emica: o par cobegin .. coend
O Comando COBEGIN
O comando
S0;
cobegin
S1
|| S2
|| S3
coend;
S4
prescreve a execuc~ao de S0, seguida da execuc~ao em paralelo de S1, S2 e
S3,
seguida da execuc~ao de S4
nenhuma suposic~ao e feita sobre as velocidades relativas de S1,
S2
e S3
Grafo de Preced^encias
grafo dirigido que expressa relac~oes de preced^encia entre possveis
execuc~oes dos comandos de um programa paralelo
nos : execuc~oes de comandos
arcos : relac~oes imediatas de preced^encia
~ PARALELA ASSINCRONA
2.2. PROGRAMACAO
Processo pai
S0
S1
S2
21
S3
Processos filhos
S4
N~ao existe relac~ao de preced^encia entre S1, S2 e S3
S1, S2 e S3 s~ao ditos paralelos , ou concorrentes
Insistindo, n~ao fazemos suposico~es sobre velocidades relativas dos
processos
2.2.3 Exemplos de Programas Paralelos
Somas
de 4 numeros:
int x, y, z, w, s1, s2, s;
...
cobegin
s1 = x + y
|| s2 = z + w
coend;
s = s1 + s2
{ com paralelismo efetivo, o tempo total e de 2 operac~oes de soma (o
tempo sequencial seria de 3 somas)
de 2 vetores:
int A[100],B[100],C[100],i;
...
cobegin
||(0..99) C[i] = A[i] + B[i];
coend
~ A PROGRAMACAO
~ PARALELA ASSINCRONA
22CAPITULO 2. INTRODUCAO
Exerccio 2.2.1 Qual e o tempo mnimo para se fazer esta soma sequencialmente? E em paralelo?
Sistema Operacional em Batch com SPOOL
readFile(cardReader, inputFile);
while (true) do {
exec(inputFile, outputFile);
cobegin
printFile(outputFile, printer);
|| readFile(cardReader, inputFile);
coend;
}
readFile
exec
readFile
printFile
exec
readFile
printFile
exec
Aninhamento
S0;
cobegin
S1;
|| S2;
cobegin
S3;
|| S4;
coend;
S5;
^
2.3. SEMANTICA
DE PROGRAMAS PARALELOS
23
|| S6;
coend;
S7;
Exerccio 2.2.2 Qual e o grafo de preced^encias associado a este programa?
2.3 Sem^antica de Programas Paralelos
2.3.1 Conitos
O que sera impresso por este programa?
Programa IncDec:
n = 4;
cobegin
n = n + 3;
|| n = n * 10
coend;
printf(n);
Devemos escolher uma sem^antica que torne confortavel a programac~ao e sua
implementac~ao.
Sem^antica sequencial : o efeito do comando paralelo deve ser equiva
lente ao da execuc~ao sequencial de seus subcomandos (e o problema do
implementador de um pipeline)
Sem^antica n~ao-determinstica : o efeito do comando paralelo deve
ser equivalente ao de uma das composic~oes seriais de seus subcomandos
Com a sem^antica sequencial, este programa escreveria 70
Com a sem^antica n~ao-determinstica, este programa poderia escrever 70
ou 43 (e nada diferente disto!)
A sem^antica n~ao-determinstica e a mais utilizada, por estar em acordo
com a hipotese de independ^encia das velocidades relativas
Programa IncDec Compilado para um Monoprocessador
Adotamos a sem^antica n~ao determinstica. Mas sera que o programa vai mesmo
imprimir 70 ou 43?
Consideremos o seguinte programa, resultado de uma compilac~ao tradicional de
IncDec (vamos omitir o codigo correspondente a criac~ao dos processos)
~ A PROGRAMACAO
~ PARALELA ASSINCRONA
24CAPITULO 2. INTRODUCAO
n = 4;
cobegin
LDA n; ADD 3; STA n;
||
LDA n; MULT 10; STA n;
}
coend;
printf(n);
Compartilhamento de um monoprocessador
A gura abaixo ilustra a forma tradicional de compartilhamento de um processa-
Add
Mu
Nucleo
Interrupcao
Salva registradores
Recarrega registradores
RTI
Interrupcao
Salva registradores
Recarrega registradores
RTI
dor; voltaremos a este ponto na seca~o3.
Registradores s~ao variaveis locais!
^
2.3. SEMANTICA
DE PROGRAMAS PARALELOS
25
Uma computac~ao do programa IncDec compilado
LDA n
(A = 4)
LDA n
ADD 3
STA n
(A = 4)
(A = 7)
(n = 7)
MULT 10
STA n
(A = 40)
(n = 40)
Este resultado (n=40) n~ao pode ser inferido do programa IncDec original
) a sem^antica do programa IncDec n~ao e denida!
2.3.2 Sem^antica Operacional
Um programa paralelo tem a sua sem^antica denida se todos os seus
possveis comportamentos podem ser inferidos de sua codicac~ao original
Para isto, a atomicidade de qualquer conjunto de ac~oes com possvel
execuc~ao em paralelo deve ser garantida
Um conjunto de duas ou mais ac~oes e dito at^omico quando o efeito de sua
execuc~ao em paralelo e serializavel , isto e, equivalente ao efeito da
execuc~ao sequencial destas ac~oes em pelo menos uma ordenac~ao
Reparem que a noc~ao de atomicidade se aplica a um conjunto de ac~oes, e
n~ao a uma ac~ao em particular
Implementac~ao de ac~oes at^omicas
o hardware de qualquer computador garante a atomicidade de
certos conjuntos de instruc~oes
ex.: um monoprocessador simples so pode ser interrompido entre duas
instruc~oes, o que faz com que o conjunto de todas as suas instruc~oes seja
at^omico
nestes casos a inibic~ao de interrupc~oes pode ser usada para garantir a
formac~ao de blocos de instruc~oes com atomicidade garantida.
o programa abaixo imprime 43 ou 70, como queramos:
~ A PROGRAMACAO
~ PARALELA ASSINCRONA
26CAPITULO 2. INTRODUCAO
n = 4
cobegin
DI; /* disable interrupts */
LDA n; ADD 3; STA n;
EI; /* enable interrupts */
||
DI;
LDA n; MULT 10; STA n;
EI;
coend;
printf(`n);
2.3.3 Comandos Conitantes
a noc~ao de comandos conitantes e utilizada para determinar a
atomicidade de conjuntos de comandos
sejam:
W (c) o conjunto de posic~oes de memoria escritas pelo comando c
R(c) o conjunto de posic~oes de memoria lidas pelo comando c
o comando c1 esta em conito com o comando c2 se
W (c1 ) \ W (c2 ) 6= ;; ou
W (c1 ) \ R(c2 ) 6= ;; ou
R(c1 ) \ W (c2 ) 6= ;
e (quase sempre) at^omico
= n * 10) n~
ao e at^omico
= 2*n) n~
ao e at^omico
(a = 0, b = 0)
(n = n + 3, n
(n = n + 3, x
Atomicidade em Linguagens de Alto Nvel
Espera-se que qualquer conjunto de ac~oes denidas por comandos n~ao
conitantes seja at^omico
A noc~ao de comandos conitantes nem sempre e de facil aplicac~ao, pois
depende do mapeamento de variaveis de alto nvel na memoria
Par^ametros formais s~ao um caso particularmente complicado
Variaveis locais em C, Pascal ou Java nunca constituem fonte de
conitos, pois normalmente s~ao alocadas nas pilhas exclusivas dos
processos
^
2.3. SEMANTICA
DE PROGRAMAS PARALELOS
27
Quando um programa prescreve a execuc~ao em paralelo de comandos conitantes, diz-se que ele esta provocando uma race condition (um nome
tradicional mas infeliz, pois deixa a impress~ao de que um programa paralelo cujos resultados dependem das velocidades relativas dos processos
esta obrigatoriamente errado)
Um programa sequencial sintaticamente correto possui uma sem^antica
bem denida, mesmo que n~ao seja aquela que se desejava
E difcil fazer o mesmo com uma linguagem de alto nvel sem perda de
paralelismo: (A[i]++,A[j]--) s~ao conitantes?
A garantia de uma sem^antica bem denida ca aos cuidados do
programador!
Quais numeros este programa pode imprimir?
int n;
void soma100(void) {
int i;
for(i=0; i <= 100; i++) {
LDA n; ADD 1; STA n;
}
}
void main(void) {
n = 0;
cobegin
P1:: soma100();
|| P2:: soma100();
coend;
printf(n)
}
2.3.4 Resumo
Paralelismo 6= Programac~ao Paralela
A correc~ao de um programa paralelo assncrono n~ao deve depender das
velocidades relativas dos processos
A express~ao do paralelismo e relativamente simples
Conitos abrem a possibilidade de programas sintaticamente corretos n~ao
possuirem sem^antica denida
Programas com sem^antica denica podem ter um conjunto de computac~oes complexo e surpreendente
~ A PROGRAMACAO
~ PARALELA ASSINCRONA
28CAPITULO 2. INTRODUCAO
2.4 Regi~oes Crticas
O Par Produtor-Consumidor: Processos
Produtor
Consumidor
Buffer
Produtor-Consumidor: Primeira Tentativa
void Produce(void) {
while (true) do {
... /* produz o caracter c */
while(!Put(c));
/* insiste ate conseguir colocar no buffer*/
}
}
void Consume(void) {
while (true) do {
while(!Get(&c)); /* insiste ... */
... /* consome o caracter c */
}
}
void main(void) {
cobegin
Produce(); || Consume();
coend
}
O Par Produtor-Consumidor: Buer
char B[10];
~ CRITICAS
2.4. REGIOES
29
int p=0, c=0, n=0;
int Put(char x) {
boolean ok = false;
if(n < 10) {
B[p] = x; p = (p+1) % 10; n++; ok =
}
return ok;
}
true;
int Get(char *x) {
boolean ok = false;
if (n > 0) {
*x = B[c]; c = (c+1) % 10; n--; ok = true;
}
return ok;
}
Programac~ao correta para uso sequencial
Incorreta para uso em paralelo , pois ha conito na variavel n
2.4.1 Exclus~ao Mutua
Regi~oes crticas s~ao trechos de codigo que tratam variaveis em conito
Exclus~ao mutua : soluc~ao mais simples para se obter a sem^antica n~ao
determinstica
Pode-se usar variaveis do tipo key , com as operac~oes lock e unlock
Todas as regi~oes crticas devem ser colocadas entre pares lock e unlock:
key mutex;
...
lock(mutex);
regiao critica
unlock(mutex)
Um processo que executa lock sobre uma chave destravada trava a chave
e continua sua progress~ao
Um processo que executa lock sobre uma chave travada tem a sua execuc~ao suspensa
~ A PROGRAMACAO
~ PARALELA ASSINCRONA
30CAPITULO 2. INTRODUCAO
Um processo que executa unlock destrava a chave, e permite que outros
processos a espera desta chave tentem trava-la
Nenhuma suposic~ao deve ser feita sobre a poltica de escolha do vencedor
Uma chave e travada por no maximo um processo de cada vez
Buer com exclus~ao mutua
key mutex;
char B[10];
int p=0, c=0, n=0;
int Put(char x) {
boolean ok = false;
lock(mutex)}
if(n $<$ 10) {
B[p] = x; p = (p+1) % 10; n++; ok = true;
}
unlock(mutex);
return ok;
}
int Get(char *x) {
boolean ok = false;
lock(mutex);
if (n > 0) {
*x = B[c]; c = (c+1) % 10; n--; ok = true;
}
unlock(mutex)
return ok;
}
O paralelismo e perdido no acesso ao buer, mas ...
o consumo e a produc~ao de caracteres continuam em paralelo!
Buer com sincronizac~ao interna
Vamos agora simplicar o uso do buer, embutindo em seu codigo a sincronizac~ao que era feita pelos clientes:
void Produce(void)
char c;
while (true) {
~ CRITICAS
2.4. REGIOES
31
... /* Produz o caracter c */
Put(c)} /* a sincronizacao eh problema do buffer */
}
}
void Consume(void) {
char c;
while (true) {
Get(&c);
... /* consome c */
}
}
void main(void) {
cobegin
Produce(); || Consume();
coend
}
Buer com sincronizac~ao interna: programac~ao sujeita a bloqueios
char B[10];
int p = 0, c = 0, n = 0;
key mutex;
void Put(char x) {
lock(mutex);
while (n >= 10);
/* espera por uma posicao vazia */
B[p] = x; p = (p+1) % 10; n++;
unlock(mutex);
}
void Get(char *x) {
lock(mutex);
while (n <= 0) ;
/* espera por uma posicao cheia */
*x = B[c]; c = (c+1) % 10; n--;
unlock(mutex);
}
Deadlocks
Se p. ex. o produtor encontrar n 10, entrara em loop de espera, de
posse da chave!
~ A PROGRAMACAO
~ PARALELA ASSINCRONA
32CAPITULO 2. INTRODUCAO
Situac~oes de bloqueio como esta s~ao conhecidas como pelo termo em ingl^es
deadlock
Um deadlock e caracterizado por uma espera circular
Exemplo: o processo p1 esta de posse do recurso r1 , e precisa do recurso
r2 ; o processo p2 esta de posse de r2 , e precisa de r3 ; p3 esta de posse de
r3 , e precisa de r1 para progredir.
No caso acima, o produtor tem a chave, e precisa de uma posic~ao vazia; o
consumidor tem a posica~o vazia, e precisa da chave.
Programac~ao com espera ocupada
char B[10];
int p = 0, c = 0, n = 0;
key mutex;
void Put(char x) {
lock(mutex);
while (n >= 10) {unlock(mutex); lock(mutex);}
/* espera por uma posicao vazia */
B[p] = x; p = (p+1) % 10; n++;
unlock(mutex);
}
void Get(char *x) {
lock(mutex);
while (n <= 0) { unlock(mutex); lock(mutex); }
/* espera por uma posicao cheia */
*x = B[c]; c = (c+1) % 10; n--;
unlock(mutex);
}
Programac~ao correta, mas com espera ocupada
A espera ocupada e caracterizada por testes repetidos por uma condic~ao
que impede o progresso de um processo, e que so pode ser alterada por
outro processo
Pode levar a desperdcios de tempo de processador
2.4.2 Liberac~ao do Processador
A espera ocupada pode ser evitada com o uso de variaveis do tipo bed ;
~ CRITICAS
2.4. REGIOES
33
as operac~oes associadas s~ao wait(bed b; key k) e wakeup(bed b;
key k)
o processo que executa wait(b,k) deve estar de posse da chave k ; a chave k
e liberada; o processador e liberado, e um descritor e colocado numa la
associada a cama b
o processo que executa wakeup(b,k) tambem deve faz^e-lo de posse da chave
k ; todos os processos na la associada a b s~ao \acordados", e passam a
disputar a chave k, que n~ao e liberada com esta operac~ao
Buer com Liberac~ao do Processador
char B[10];
int p = 0, c = 0, n = 0;
key mutex;
bed b;
void Put(char x) {
lock(mutex);
while (n >= 10) wait(b,mutex);
/* espera por uma posicao vazia */
B[p] = x; p = (p+1) % 10; n++;
wakeup(b,mutex);
unlock(mutex);
}
void Get(char *x) {
lock(mutex);
while (n <= 0) wait(b,mutex);
/* espera por uma posi\c{c}\~{a}o cheia */
*x = B[c]; c = (c+1) % 10; n--;
wakeup(b,mutex);
unlock(mutex);
}
2.4.3 Propriedades de programas paralelos e o problema
dos Leitores e Escritores
A exclus~ao mutua e o meio mais simples de se obter um comportamento serializavel.
O paralelismo e eliminado nas regi~oes crticas, e a serializabilidade decorre trivialmente: o comportamento e serializavel porque e serial.
~ A PROGRAMACAO
~ PARALELA ASSINCRONA
34CAPITULO 2. INTRODUCAO
As vezes a restric~ao imposta ao paralelismo e forte demais, como no classico
problema dos leitores e escritores :
Diversos processos acessam uma mesma tabela
Processos leitores apenas consultam esta tabela
Processos escritores podem modica-la
Durante uma operac~ao de escrita o acesso a tabela deve ser restrito a um
unico processo escritor
N~ao existem restric~oes a leituras simult^aneas
Escritor: ... requestWrite(); /* write */ ; releaseWrite();
Leitor: ... requestRead(); /* read */ ; releaseRead();
Leitores e Escritores: 1a soluc~ao
key mutex; bed b;
int nr = 0, nw = 0;
void requestWrite(void) {
lock(mutex);
while((nr $>$ 0) \verb#||# (nw $>$ 0)) {
wait(b,mutex);
}
nw++;
unlock(mutex);
}
void requestRead(void) {
lock(mutex);
while(nw $>$ 0) {
wait(b,mutex);
}
nr++;
unlock(mutex);
}
Leitores e Escritores: 1a soluc~ao (continuac~ao)
void releaseWrite(void) {
lock(mutex);
nw--;
~ CRITICAS
2.4. REGIOES
35
wakeup(b,k);
unlock(mutex);
}
void releaseRead(void) {
lock(mutex);
nr--;
wakeup(b,k);
unlock(mutex);
}
Leitores e Escritores: Comentarios
Um ponto importante a ser observado nesta soluc~ao e a tranquilidade garantida
pela construc~ao
while (condition) {
wait(b,mutex);
}
/* sabemos que !condition \'{e} valida aqui! */
Um processo acordado n~ao cona nos testes sobre os dados compartilhados
realizados antes de ir dormir;
Muito importante, pois como a chave e liberada ao dormir, outro processo pode
ter modicado estes dados.
Leitores e Escritores: Propriedades
Alguns autores classicam as propriedades de programas paralelos em dois grupos:
Invari^ancia , ou seguranca , ou safety : uma coisa ruim nunca vai
acontecer
Progresso , ou liveness : uma coisa boa sempre vai acontecer
A 1a soluc~ao para os leitores e escritores tem as seguintes propriedades de invari^ancia:
Nunca teremos dois ou mais processos escritores escrevendo simultaneamente
Nunca teremos um escritor escrevendo e um ou mais leitores lendo
simultaneamente
Nunca teremos uma espera circular congurando um deadlock
~ A PROGRAMACAO
~ PARALELA ASSINCRONA
36CAPITULO 2. INTRODUCAO
Invari^ancia
Propriedades de invari^ancia s~ao demonstradas por induc~ao , ou seja, para
mostrar que P e um invariante, devemos mostrar que
1. P e valido inicialmente
2. toda operac~ao sobre a estrutura de dados compartilhada que se inicia com
P valido deixa P valido
Por \operac~ao" deve ser entendida toda modicac~ao feita com a posse da chave.
A construc~ao while (condition) do wait(b,k) simplica muito este raciocnio
indutivo.
Progresso
Uma propriedade de progresso que seria interessante para o problema dos leitores e escritores seria:
Toda requisic~ao feita por processo leitor ou escritor sera satisfeita ao
m de uma espera nita
Nossa soluc~ao teria esta propriedade?
Para ter alguma chance de ser satisfeita, nos devemos introduzir as hipoteses:
1. toda operac~ao de leitura ou escrita termina ao m de um tempo nito
2. a velocidade de progresso de todos os processos que n~ao est~ao dormindo
e estritamente positiva
Mas mesmo com estas hipoteses nossa soluc~ao n~ao satisfaz a propriedade de
progresso acima, porque:
um escritor pode esperar indenidamente enquanto processos leitores v~ao
se revezando no uso da estrutura de dados, e
um leitor pode esperar indenidamente enquanto processos escritores fazem o mesmo tipo de conspirac~ao.
Nestes casos n~ao se congura um bloqueio do sistema, mas um processo tem o
seu progresso impedido pela ac~ao de outros processos.
Starvation
Diz-se de um programa que n~ao satisfaz a uma propriedade de progresso que
ele e injusto , pois permite que alguns processos morram de inanic~ao , ou
starvation .
~ CRITICAS
2.4. REGIOES
37
Programas \justos" s~ao tambem chamados de equ^animes .
A propriedade de justica e conhecida em ingl^es pelo termo fairness .
Estes termos devem ser interpretados com frieza tecnica: um programa injusto
pode ser mais adequado para uma certa tarefa do que um programa justo.
Tudo depende da especicac~ao do problema: um escalonador n~ao equ^anime que
privilegie tarefas urgentes como desligar um reator at^omico no caso de super
aquecimento e evidentemente muito melhor que um escalonador justo.
Propriedades de progresso exigem tecnicas mais elaboradas de prova, porque:
Pode-se mostrar que um algoritmo n~ao obedece a uma especicac~ao de
invari^ancia exibindo-se uma computac~ao que viole esta especicac~ao
A inanic~ao so se revela em computac~oes innitas, e por isto exige uma
demonstrac~ao formal de exist^encia ou inexist^encia
Leitores e Escritores: Soluc~ao Justa
Uma tecnica simples e poderosa para se impor um comportamento justo e o uso
de tickets , como nos bancos ou lojas de reserva de passagens
Ao chegar, um cliente pega um ticket;
Os tickets s~ao numerados sequencialmente, e determinam a ordem de atendimento
Tickets crescem monotonamente, e indenidamente;
Com um numero razoavel de bits consegue-se programas que duram seculos.
TicketQueue waiting;
...
void requestWrite() {
lock(mutex);
int myTicket = waiting.getTicket();
while ((nW > 0) || (nR > 0)||(!waiting.isTheBest(rq))) {
wait(b,mutex);
}
nW++;
waiting.ok(myTicket);
unlock(mutex);
}
void requestRead() {
~ A PROGRAMACAO
~ PARALELA ASSINCRONA
38CAPITULO 2. INTRODUCAO
lock(mutex);
int myTicket = waiting.getTicket();
while ((nW > 0) ||(!waiting.isTheBest(myTicket))) {
wait(b,mutex);
}
nR++;
waiting.ok(myTicket);
wakeup(b,mutex);
unlock(mutex);
}
void releaseWrite() {
lock(mutex);
nW--;
wakeup(b,mutex);
unlock(mutex);
}
void releaseRead() {
lock(mutex);
nR--;
wakeup(b,mutex);
unlock(mutex);
}
TicketQueue
int ticket = 0;
OrderedQueue q; // fila ordenada com operacoes put, top e pop
int getTicket() {
q.put(++ticket);
return ticket;
}
boolean isTheBest(int ticket) {
if (q.top() != null){
return ticket == q.top();
}
return true;
}
void ok(int ticket) {
if (ticket != q.pop()) { //pop() devolve o melhor e o retira da lista
ERRO!;
~ CRITICAS
2.4. REGIOES
39
}
}
2.4.4 Imposic~ao de Polticas de Escalonamento: Programac~ao de um Servidor de Impressora
Uma impressora e compartilhada por diversos processos
Seu servidor deve garantir a exclus~ao mutua no seu uso
Soluc~ao trivial: usar uma chave para controlar o acesso:
key printerKey;
void print(file F) {
lock(printerKey);
/* impressao de F */
unlock(printerKey);
}
Inconvenientes:
1. se quisermos acrescentar procedimentos no estilo lpq e lprm para vericac~ao e alterac~ao do estado da la de impress~ao, teramos que ter acesso
ao estado da la da chave, o que nem sempre e possvel
2. o escalonamento da impressora e feito por um nucleo de multiprogramac~ao,
impossibilitando a imposic~ao de qualquer poltica de uso da impressora
Servidor de Impressora: Soluc~ao com Erro
Um exemplo para mostrar como o uso do if ao inves do while pode ser
muito perigoso:
void print(ProcessId client, File f) {
requestPrinter(client);
/* impress\~{a}o de F */
releasePrinter(client);
}
boolean busy = false; key mutex; bed b;
Queue q = new Queue();
ProcessId owner;
~ A PROGRAMACAO
~ PARALELA ASSINCRONA
40CAPITULO 2. INTRODUCAO
void requestPrinter(ProcessId client) {
lock(mutex);
q.enter(client);
if (busy) { wait(b,mutex); }
busy = true;
q.leave(client);
owner = client;
unlock(mutex);
}
void releasePrinter(ProcessId client) {
lock(mutex);
busy = false;
owner = null;
wakeup(b, mutex);
unlock(mutex);
}
O escalonamento continua sendo decidido pelo nucleo, mas isto n~ao e o
mais grave;
Um processo acordado pode perder a disputa pela chave para outro processo executando lock;
Dois - ou mais - processos poder~ao ser autorizados a usar a
impressora simultaneamente!
Servidor de Impressora: Soluc~ao \correta"
Substituindo if por while, corrigimos o problema de desrespeito a propriedade
de invari^ancia da exclus~ao mutua no uso da impressora:
boolean busy = false; key mutex; bed b;
Queue q = new Queue();
ProcessId owner;
void requestPrinter(ProcessId client) {
lock(mutex);
q.enter(client);
while (busy) { wait(b,mutex); }
busy = true;
q.leave(client);
owner = client;
unlock(mutex);
~ CRITICAS
2.4. REGIOES
41
}
void releasePrinter(ProcessId client) {
lock(mutex);
busy = false;
owner = null;
wakeup(b, mutex);
unlock(mutex);
}
Mas continuamos com o escalonamento imposto pelo nucleo!
SJF: Shortest Job First
O uso de um recurso como uma impressora pode ser melhorado com uma poltica
de escalonamento
Shortest Job First , ou SJF , privilegia os servicos menores, propiciando
um tempo medio de espera menor
Para forcar esta poltica, podemos criar uma la de requisic~oes, similar a TicketQueue usada para impor fairness no problema dos leitores e escritores (sec~ao
2.4.3).
Nos vamos aqui procurar evitar o problema de eci^encia causado ao se acordar
todos os processos usando wakeup, sendo que apenas um deles tera condic~oes
de progresso, enquanto todos os outros voltar~ao para dormir.
Como wakeup acorda todos os processos dormindo numa cama, vamos precisar
de diversas camas para implementar o nosso escalonamento. Vamos acordar
somente o processo selecionado pela poltica de escalonamento.
O Escalonador SJF - 1a vers~ao
A seguinte estrutura de dados e conveniente para o registro de uma requisic~ao
de impress~ao:
class Request {
int fileSize;
Bed bed;
ProcessId client;
}
SJFQueue waiting;
Com isto, temos:
~ A PROGRAMACAO
~ PARALELA ASSINCRONA
42CAPITULO 2. INTRODUCAO
void requestPrinter(ProcessId client, int fileSize) {
lock(mutex);
Request rq = waiting.getRequest(client, fileSize);
while (busy) wait(rq.bed, mutex);
q.ok(rq);
busy = true;
unlock(mutex);
}
void releasePrinter() {
lock(mutex);
busy = false;
wakeup((waiting.top().bed, mutex);
unlock(mutex);
}
SJFQueue
OrderedQueue q = new OrderedQueue(new SizeComparator());
/* a fila \'{e} criada com o criterio de comparacao correspondente */
Request getRequest(ProcessId client, int jobSize) {
Request rq = new Request(client, jobSize);
q.put(rq);
return rq;
}
void ok(Request rq) {
q.del(rq);
}
Request top() {
return (Request) q.top();
}
Mas ainda existem chances de um arquivo grande furar a la! Como?
Qual seria uma soluc~ao para este problema?
O Escalonador SJF - 2a vers~ao
void requestPrinter(ProcessId client, int fileSize) {
lock(mutex);
Request rq = waiting.getRequest(client, fileSize);
while (busy || !waiting.isTheBest(rq)) wait(rq.bed, mutex);
~ CRITICAS
2.4. REGIOES
43
q.ok(rq);
busy = true;
unlock(mutex);
}
void releasePrinter() {
lock(mutex);
busy = false;
wakeup((waiting.top().bed, mutex);
unlock(mutex);
}
SJFQueue
OrderedQueue q = new OrderedQueue(new SizeComparator());
/* a fila \'{e} criada com o criterio de comparacao correspondente */
Request getRequest(ProcessId client, int jobSize) {
Request rq = new Request(client, jobSize);
q.put(rq);
return rq;
}
void ok(Request rq) {
q.del(rq);
}
boolean isTheBest(Request rq ) {
return ( rq == top() );
}
Request top() {
return (Request) q.top();
}
2.4.5 Conclus~oes
1. A exclus~ao mutua e a ferramenta basica para se obter um comportamento
serializavel de operac~oes sobre uma estrutura de dados compartilhada
2. Ferramentas para liberac~ao do processador s~ao indispensaveis na pratica
3. Escalonamentos com polticas arbitrarias podem ser implementados com
uma programac~ao mais elaborada
~ A PROGRAMACAO
~ PARALELA ASSINCRONA
44CAPITULO 2. INTRODUCAO
4. Existem propriedades de programas paralelos que n~ao t^em similares para
programas sequenciais, como a aus^encia de deadlocks, ou starvation
5. Resta o problema da implementac~ao de lock e unlock; nos voltaremos a
este ponto na sec~ao3.
2.5 Exerccios
Exerccio 2.5.1 (Quicksort paralelo) Proponha uma vers~ao paralela para o
Quicksort. Mostre o grafo de preced^encias associado ao procedimento. Supondo
que a mediana de cada partic~ao e sempre escolhida como piv^o, calcule o tempo
necessario para a ordenac~ao de n elementos por um computador com muitos
processadores. Considere nulo o tempo necessario para a criac~ao e termino de
processos. Observac~ao: Classicac~ao em paralelo constitui um campo ativo
de pesquisa; um panorama da area pode ser encontrado em [Bitton et al., 1984]
Exerccio 2.5.2 (Comparac~ao e Troca em paralelo) (Soluc~ao na sec~ao2.6.2
) Proponha um \sort" paralelo baseado no algoritmo de comparac~ao e troca, onde fases pares e mpares se alternam. Nas fases pares os elementos de ndice par
s~ao comparados com os seus sucessores imediatos, sendo feitas trocas nas posic~oes desordenadas. As fases mpares s~ao analogas. Calcule o tempo necessario
para a ordenac~ao de um vetor com n elementos.
Exerccio 2.5.3 (Transaco~es) (Soluc~ao na sec~ao2.6.3 ) Considere o seguinte
programa:
a = 1; b = 1;
cobegin
T1:: a := a + 100; b := b + 100;
||
T2:: a := a * 2; b := b * 2;
coend
Na terminologia introduzida por [Eswaran et al., 1976], uma transac~ao e
uma unidade de consist^encia , isto e, um procedimento que, se executado isoladamente, preserva a consist^encia de um banco de dados. Supondo que
a = b e a condic~ao de consist^encia no programa acima, T1 e T2 seriam transac~oes. O controle de concorr^encia de um banco de dados deve cuidar para que
o efeito de transac~oes executadas em paralelo seja equivalente a sua execuc~ao
numa sequ^encia qualquer. Acrescente ao programa acima comandos de sincronizac~ao que garantam a serializabilidade de sua execuc~ao. Procure maximizar
o paralelismo, n~ao utilizando uma unica regi~ao crtica.
2.5. EXERCICIOS
45
Exerccio 2.5.4 (Escalonamento SJF) Uma impressora e compartilhada por
diversos processos. Cada processo cliente submete seu arquivo chamando printerScheduler.submit(int leSize); Seu servidor deve:
1. garantir a exclus~ao mutua no uso da impressora, e
2. dar prioridade aos arquivos menores, impondo uma poltica SJF ( Shortest
Job First) no escalonamento.
Exerccio 2.5.5 (Aging) Arquivos muito grandes podem ser preteridos indenidamente numa poltica SJF. Mude a soluc~ao do problema anterior, usando
a tecnica de aging (envelhecimento), onde:
a prioridade inicial de cada submiss~ao e o tamanho do arquivo a ser impresso;
cada vez que um processo ganha a impressora, ele aumenta a prioridade
de todos os processos que est~ao esperando.
Compare a poltica de aging com as polticas SJF e FIFO.
Exerccio 2.5.6 (Controlando o nvel de paralelismo) Modique a soluc~ao
para o problema dos leitores e escritores de forma a permitir que no maximo 4
leitores consigam ler simultaneamente.
Exerccio 2.5.7 (A rvore-B) (Soluc~ao na sec~ao2.6.4 ) Um sistema de controle de concorr^encia de uma arvore-B pode adotar a seguinte sistematica:
pode-se ter um numero arbitrario de leituras simult^aneas;
um processo escritor (que modica a arvore) comporta-se da seguinte maneira:
{ requisita acesso exclusivo com relac~ao aos outros escritores; leitores
podem continuar lendo, e novos leitores podem entrar;
{ obtida a autorizac~ao, caminha na arvore-B ate atingir o ponto onde
faz efetivamente a modicac~ao;
{ requisita ent~ao a extens~ao aos leitores da exclusividade do acesso;
{ faz a modicac~ao, e libera a arvore.
Programe um modulo que faca este controle de concorr^encia.
Observac~ao : este controle de concorr^encia e ing^enuo, restringindo desnecessariamente o paralelismo. Algoritmos muito mais ecientes podem ser encontrados por exemplo em [Johnson and Shasha, 1993].
~ A PROGRAMACAO
~ PARALELA ASSINCRONA
46CAPITULO 2. INTRODUCAO
Exerccio 2.5.8 (Pool de Recursos Id^enticos) R recursos id^enticos s~ao compartilhados por C processos clientes. Um recurso n~ao pode ser utilizado por mais
de um processo simultaneamente. A vida de um processo cliente segue o ciclo:
pensa;
requisita n recursos, onde n e um valor arbitrario entre 1 e R;
utiliza os n recursos;
devolve os n recursos.
a. Proponha uma soluc~ao que utilize a tecnica de aging para aumentar a taxa
de utilizac~ao dos recursos mantendo a garantia de equanimidade.
b. Argumente a favor da correc~ao da soluc~ao proposta.
Exerccio 2.5.9 (Buer com mutiplos clientes) Encontre uma soluc~ao equ^anime
(livre de starvation ) para o problema do compartilhamento de um buer limitado por um numero qualquer de processos produtores e consumidores.
2.6 Respostas
2.6.1 Quicksort Paralelo
(Exerccio 2.5.1)
void quicksort(int a[], int left, int right) {
if(left < right) {
int pivot = choosePivot(a,left,right);
Partition p = partition(a, left, right, pivot);
cobegin
quicksort(a,left,p.right);
||
quicksort(a,p.left,right);
coend;
}
}
Analise : Supondo que o pivot escolhido e sempre a mediana, o algoritmo
fara n comparac~oes na primeira partic~ao. No segundo nvel de recursividade ser~ao feitas duas partic~oes, cada uma de tamanho n=2; no total ser~ao
tambem feitas n comparaco~es. Entretanto, como as partic~oes s~ao feitas simultaneamente, o tempo gasto sera proporcional a n=2. No terceiro nvel,
2.6. RESPOSTAS
47
teremos quatro partic~oes simult^aneas, cada uma de tamanho n=4, e assim
por diante. Desta forma, o tempo total gasto sera dado pela soma
T = n1 + n2 + + 1 = n (2 ; 1=n)
Temos portanto um sort com complexidade (para o melhor caso) de O(n),
melhor do que o limite de O(n log(n) para algoritmos sequenciais.
O metodo partition pode ser implementado com paralelismo, o que
reduz a metade o tempo ideal de processamento, mas n~ao altera a ordem
de complexidade.
2.6.2 Comparac~ao e Troca em Paralelo
(Exerccio 2.5.2)
void sort(int a[],int
for(int i = 0; i <
cobegin
||(k=0..n/2)
coend;
cobegin
||(k=1..n/2)
coend;
}
}
n) {
n/2; i++) {
compareAndSwap(a[2k], a[2k+1]);
compareAndSwap(a[2k-1],a[2k]);
Claramente temos um algoritmo de complexidade O(n), para o pior caso, com
desempenho bem superior ao do Quicksort paralelo. Este e um exemplo de
que paralelizac~oes de bons algoritmos sequenciais podem resultar em algoritmos
paralelos ruins, e vice-versa.
2.6.3 Transac~oes
(Exerccio 2.5.3)
key mutexA, mutexB;
a = 1; b = 1;
cobegin
T1::
lock(mutexA); a = a + 100;
lock(mutexB); unlock(mutexA);
b = b + 100; unlock(mutexB);
||
~ A PROGRAMACAO
~ PARALELA ASSINCRONA
48CAPITULO 2. INTRODUCAO
T2::
lock(mutexA); a = a * 2;
lock(mutexB); unlock(mutexA);
b = b * 2; unlock(mutexB);
coend
Obs.: a tecnica utilizada nesta soluca~o e bastante geral, sendo conhecida
como two-phase locking (veja a seca~o 7), pois nenhum lock e adquirido
apos o relaxamento de qualquer lock.
Exerccio 2.6.1 O que aconteceria se tivessemos T2:: b = b * 2; a = a * 2, e
empregassemos two-phase locking?
2.6.4 A rvore B
(Exerccio 2.5.7)
class BTreeConcurrencyController {
int nww = 0, nwr = 0, nr = 0;
TicketQueue q;
Bed bed;
Key mutex;
void readerRequestRead() {
lock(mutex);
Ticket myTicket = q.getTicket();
while ((nww > 0) || (!q.isTheBest(myTicket))) {
wait(bed,mutex);
}
nr++;
waiting.ok(myTicket);
wakeup(bed,mutex);
unlock(mutex);
}
void writerRequestRead() {
lock(mutex);
Ticket myTicket = q.getTicket();
while ((nww + nwr > 0) || (!q.isTheBest(myTicket))) {
wait(bed, mutex);
}
nwr++;
waiting.ok(myTicket);
wakeup(bed,mutex);
unlock(mutex);
}
2.6. RESPOSTAS
49
A rvores-B: Soluc~ao (cont)
void requestWrite() {
lock(mutex);
Ticket myTicket = q.getTicket();
while ((nr > 0) || (!q.isTheBest(myTicket))) {
wait(bed, mutex);
}
nww++; nwr--;
q.ok(myTicket);
unlock(mutex);
}
void releaseWrite() {
lock(mutex);
nww--;
wakeup(bed,mutex);
unlock(mutex);
}
void releaseRead() {
lock(mutex);
nr--;
wakeup(bed,mutex);
unlock(mutex);
}
Observac~ao : O controle de concorr^encia em arvores-B e um problema
muito estudado, e as soluc~oes conhecidas s~ao mais sosticadas, possibilitando um paralelismo bem superior ao da nossa proposta.
2.6.5 Pool de Recursos Id^enticos
(Exercicio 2.5.8)
Cliente i:
loop
...
r = randomChoice(1,R);
List myResources = pool.getResources(myProcessId, r);
/* usa os recursos na lista myResources */
pool.releaseResources(myResources);
...
end
class Pool {
~ A PROGRAMACAO
~ PARALELA ASSINCRONA
50CAPITULO 2. INTRODUCAO
Key mutex;
AgingQueue q;
List free = new List();
List getResources(ProcessId pid, int r) {
List result;
lock(mutex);
Request rq = q.getRequest(pid, r);
while ((free.count() < r) || (!q.isTheBest(rq)))) {
wait(rq.bed, mutex);
}
q.ok(rq);
wakeup(q.top().bed, mutex); /* os restantes podem servir */
result = free.getList(r);
unlock(mutex);
return result;
}
void releaseResources(List rList) {
lock(mutex);
free.put(rList);
wakeup(q.top().bed, mutex);
unlock(mutex);
}
}
class Request {
int number;
int age;
Bed bed;
ProcessId client;
}
class AgingQueue {
OrderedQueue waiting = new OrderedQueue(new NumberPlusAgeComparator());
Request getRequest(ProcessId client, int nResources) {
Request rq = new Request(client, nResources, 0);
waiting.put(rq);
return rq;
}
void ok(Request rq) {
waiting.del(rq);
waiting.getOlder();
}
2.6. RESPOSTAS
boolean isTheBest(Request rq ) {
return ( rq == waiting.top() );
}
Request top() {
return (Request) waiting.top();
}
}
51
~ A PROGRAMACAO
~ PARALELA ASSINCRONA
52CAPITULO 2. INTRODUCAO
2.7 1a Prova
Distribuic~ao: 30/09/98
Devoluc~ao por e-mail ou disponibilizac~ao na pagina do aluno: 01/10/98
A prova e estritamente individual.
A consulta ao material do curso e permitida, mas por favor n~ao procurem
soluc~oes prontas em artigos por a. Construam suas proprias soluc~oes. A
avaliac~ao de alunos e do professor e o objetivo essencial desta prova.
Gabarito
2.7.1 1a Quest~ao
Descreva os conceitos listados a seguir, explicando sua import^ancia no contexto
da programac~ao paralela:
a. processos assncronos
b. exclus~ao mutua
c. serializabilidade
d. espera ocupada
e. equanimidade
2.7.2 2a Quest~ao
Considere uma ponte estreita, com passagem para um so carro, em uma estrada
que permite trafego em duas m~aos, de leste para oeste e no sentido contrario.
Um carro que se dirija para leste so pode entrar na ponte se n~ao houver nenhum
carro na ponte vindo na direc~ao contraria. Dois ou mais carros podem estar
sobre a ponte, desde que estejam trafegando na mesma direc~ao. Programe um
sincronizador para a ponte, usado por processos associados aos carros.
2.7.3 3a Quest~ao
Resolva o problema dos leitores e escritores impondo a seguinte poltica:
um leitor n~ao pode comecar a ler se algum escritor estiver esperando, a
n~ao ser no caso abaixo;
2.7. 1A PROVA
53
ao m de uma operac~ao de escrita, todos os leitores que estiverem esperando devem comecar a ler.
Sua soluc~ao tem problemas de starvation? Porque?
2.7.4 4a Quest~ao
Uma barbearia consiste de uma sala de espera com n cadeiras comuns, e de uma
unica cadeira de barbeiro. O barbeiro atende a um cliente de cada vez. Se um
cliente entra na barbearia e todas as cadeiras est~ao ocupadas, ele vai embora.
Se o barbeiro esta ocupado mas existem cadeiras comuns disponveis, o cliente
espera usando uma cadeira. Programe um sincronizador para a barbearia, usado
pelo processo barbeiro e por processos clientes.
2.7.5 5a Quest~ao
Uma barreira e uma construc~ao para a sincronizac~ao de processos que e
util para assegurar que todos os processos envolvidos em uma tarefa atingiram
um ponto determinado em suas computac~oes. A barreira e inicializada com um
valor inteiro. Se um processo executa bar.barrier(int b), ele e bloqueado na
barreira bar ate que o numero de processos igualmente bloqueados na barreira
atinja b, quando a progress~ao de todos os processos em espera na barreira e
liberada. Programe uma classe Barrier que ofereca este tipo de sincronizac~ao.
~ A PROGRAMACAO
~ PARALELA ASSINCRONA
54CAPITULO 2. INTRODUCAO
Cap
tulo 3
Nucleos de
Multiprogramac~ao
Objetivo de um nucleo de multiprogramac~ao: obter uma maquina virtual paralela, com primitivas de sincronizac~ao, a partir de uma maquina
sequencial com interrupc~oes
Plano da aula:
1. Interrupc~oes em PCs
2. Co-rotinas
3. Multiplexac~ao do processador
4. Camas e chaves
5. Resumo e Conclus~oes
3.0.1 Interrupc~oes em PCs
Interrupc~oes est~ao na base das tecnicas de multiplexac~ao de um monoprocessador
A construc~ao de um nucleo de multiprogramac~ao exige um conhecimento
detalhado do mecanismo de interrupc~ao da maquina alvo
Vamos estudar um nucleo para um PC-XT, que usa um processador simples, com a arquitetura Intel 8086, onde interrupc~oes entre instruc~oes, sem
memoria virtual.
Este nucleo implementa uma poltica round-robin para compartilhamento
do processador, onde o controle do processador e trocado a cada interrupc~ao do relogio
55
~
CAPITULO 3. NUCLEOS
DE MULTIPROGRAMACAO
56
O relogio e um dispositivo externo cuja unica funca~o e interromper o
processador central periodicamente; o perodo entre interrupc~oes e programavel.
O relogio n~ao e o clock do processador!
A atomicidade de trechos de codigo formados por uma unica instruc~ao e
garantida
A inibic~ao de interrupc~oes e o mecanismo usado para garantir a atomicidade de trechos mais longos de codigo.
O Controlador de Interrupc~oes
O processador principal (8086, ou 8088) possui um pino de interrupc~ao;
A este pino de interrupc~ao esta ligado um integrado, o 8259, que e um
controlador programavel de interrupc~oes
Cada dispositivo de E/S esta ligado a uma linha IRQ (Interrupt ReQuest)
do 8259
Existem 8 linhas IRQ, numeradas de 0 a 7; a IRQ 0 possui a mais alta
prioridade
Interrupc~oes podem ser inibidas tanto no 8086 como (de forma seletiva)
no 8259
A ligac~ao padr~ao num XT e:
IRQ
0
1
2
3
4
5
6
7
Dispositivo
Relogio
Teclado
Porto assncrono 1
Porto assncrono 2
Controlador de disco xo
Controlador de disco exvel
Controlador da impressora
Driver do vdeo
Interrupc~oes: Tratamento pelo Hardware
Um dispositivo que deseja interromper o 8086 \levanta" a sua IRQ, e o
8259 tenta ent~ao interromper o 8086
Ao se deixar interromper, o 8086
57
1. empilha os registradores PSW (Program Status Word), CS (Code
Segment), e IC (Instruction Counter), de forma a poder retornar ao
ponto onde foi interrompido;
2. pede ao 8259 o numero n do dispositivo que interrompeu
o 8259 transmite ao 8086 este numero n, que e igual ao numero da IRQ
+ 8 (se mais de uma IRQ estiver levantada, e o numero da IRQ de mais
alta prioridade que e transmitido ao 8086)
Ao receber n, o 8086 coloca em seu registrador CS os dois bytes com
endereco absoluto 4n, e em seu registrador IC os dois bytes com endereco
4n + 2; isto inicia o tratamento por software da interrupc~ao
Ex.: em uma interrupc~ao do relogio, n = 0, CS recebe os bytes 32 e 33, e
IC os bytes 34 e 35
Este conjunto de 4 bytes e chamado de vetor de interrupc~ao associado a
n
Interrupc~oes: Tratamento por Software
O tratador da interrupc~ao deve salvar os registradores, o que normalmente
e feito na pilha
Os valores de BP (Base Pointer) e de SP(Stack Pointer) devem ser armazenados para posterior recuperac~ao
Apos o tratamento da interrupc~ao, BP e SP devem ser restabelecidos,
os demais registradores desempilhados, e a instruc~ao RETI (Return of
interrupt) deve ser executada
3.0.2 Co-rotinas
O nucleo apresentado aqui e inspirado em Modula-2 (Wirth, 1980?), uma
linguagem sucessora do Pascal, com boas ferramentas de modularizac~ao
mas sem orientac~ao a objetos
O conceito de co-rotina implementado em Modula-2 e util para a estruturac~ao da programac~ao de uma aquina sequencial sujeita a interrupc~oes
Uma variavel do tipo co-rotina pode conter um \contexto" (no caso do
XT, essencialmente BP e SP) do processador
Trocas de contexto podem ser feitas atraves do procedimento transfer(fromCoroutine,
toCoroutine), que armazena o contexto corrente em fromCoroutine, e estabelece o contexto armazenado em toCoroutine ;
~
CAPITULO 3. NUCLEOS
DE MULTIPROGRAMACAO
58
Uma co-rotina e criada atraves de um procedimento newCoroutine(procedimento
inicial, area de trabalho)
A area de trabalho ira conter a pilha associada a esta co-rotina, e e inicializada como se esta co-rotina tivesse sido interrompida no incio de seu
procedimento inicial
Co-rotinas e Interrupc~oes
Transfer^encias de contexto tambem podem ser engatilhadas para ocorrer no momento de uma interrupc~ao, atraves do procedimento iotransfer(fromCoroutine, toCoroutine, interruptVector);
iotransfer tambem armazena o contexto corrente em FromCoroutine, e
estebelece toCoroutine
Alem disto, na ocorr^encia de uma interrupc~ao associada a interruptVector,
o contexto corrente sera armazenado em toCoroutine, e sera feita uma
transfer^encia para fromCoroutine
Importante: o contexto de uma co-rotina inclui o status de habilitac~ao ou
desabilitac~ao de interrupc~oes
3.0.3 Multiplexac~ao do Processador
Interface de um nucleo simples
Process createProcess( initialProcedure, workSpaceSize) cria um novo processo; processos lhos n~ao podem criar processos; um processo criado n~ao
comeca a rodar
void coStart() dispara todos os processos criados; o processo pai e atrasado
ate a morte dos lhos
void processEnd() indica ao nucleo o termino de um processo; so pode ser
utilizada por processos lhos
Co-rotinas e processos
A cada processo (incluindo o processo pai) deve corresponder uma corotina
Uma co-rotina extra corresponde ao nucleo
O procedimento coStart() executa um transfer da co-rotina father para a
co-rotina kernel
59
O nucleo escalona o proximo processo a ser rodado, e executa um iotransfer
da co-rotina kernel para a co-rotina escolhida, associado a interrupc~ao do
relogio
Quando o relogio interrompe, o contexto corrente e armazenado na corotina correspondente, e o contexto da co-rotina kernel e restabelecido
Multiplexac~ao do Processador entre as co-rotinas
father
kernel
coStart
transfer
p1
p2
iotransfer
interrupt
iotransfer
interrupt
iotransfer
transfer
endProcess
iotransfer
transfer
endProcess
transfer
Estruturas de Dados
Process: campos coroutine, state
Queue ready:
Coroutine fatherCoroutine, kernelCoroutine;
Process currentProcess
int nrofActiveProcesses
contem os processos prontos para rodar
esta ultima e criada
na inicializac~ao do nucleo, com o procedimento inicial schedule();
60
~
CAPITULO 3. NUCLEOS
DE MULTIPROGRAMACAO
Criac~ao de processos e coStart
class Process {
Coroutine coroutine;
byte[] workArea;
int state;
public Process(procedure initialProcedure,
int workAreaSize) {
coroutine = createCoroutine(initialProcedure,
new byte[workAreaSize]);
/* cria a co-rotina correspondente ao processo */
kernel.addProcess(this);
state = READY;
}
}
no kernel:
public void addProcess(Process p){
ready.put(p);
nrofActiveProcess++;
}
public void coStart() {
transfer(fatherCoroutine, kernelCoroutine);
}
Escalonamento e m dos processos
void schedule() {
disableInterrupts();
while(nrofActiveProcesses > 0) {
currentProcess = ready.get();
/* escolhe o proximo processo */
iotransfer(kernelCoroutine,
currentProcess.coroutine, clockInterruptVector);
if(currentProcess.state == READY)
ready.put(currentProcess);
}
transfer(kernelCoroutine, fatherCoroutine);
}
void processEnd() {
disableInterrupts();
nrofActiveProcesses--;
currentProcess.state = FINISHED;
transfer(currentProcess.coroutine, kernel);
61
}
3.0.4 Chaves e Camas
Chaves
class Key {
boolean locked;
Queue waiting;
}
void lock(Key k) {
InterruptStatus is = saveInterruptStatus();
disableInterrupts();
if(k.locked) {
k.waiting.put(currentProcess);
currentProcess.state = WAITING;
transfer(currentProcess.coroutine, kernel);
}
k.locked = true;
is.restore();
/* lock pode ser chamada por processos com interrupcoes
inibidas ou nao, e por isto o status \'{e} restabelecido
*/
}
void unlock(Key k) {
InterruptStatus is = saveInterruptStatus();
disableInterrupts();
if(k.waiting.empty()) {
k.locked = false;
} else {
Process p = k.waiting.get();
p.state = READY;
ready.put(p);
}
is.restore();
}
Camas
class Bed {
Queue waiting;
}
62
~
CAPITULO 3. NUCLEOS
DE MULTIPROGRAMACAO
void wait(Bed b, Key k) {
InterruptStatus is = saveInterruptStatus();
disableInterrupts();
currentProcess.state = WAITING;
unlock(k);
b.waiting.put(currentProcess);
transfer(currentProcess.coroutine, kernel);
is.restore();
}
void wakeup(Bed b, Key k) {
InterruptStatus is = saveInterruptStatus();
disableInterrupts();
while ((Process p = b.waiting.get()) != null) {
p.state = WAITING;
k.waiting.put(p);
}
is.restore();
}
Multiprocessadores
Em um multiprocessador com memoria compartilhada a inibic~ao de interrupc~oes n~ao e suciente para obter a exclus~ao mutua no acesso ao nucleo;
Este mecanismo e implementado por instruco~es especiais ( [Dinning, 1989]
descreve este e inumeros outros mecanismos; [Dubois et al., 1988] tambem
parece ser interessante) como
boolean testAndSet(boolean lockState, boolean newLockState)
Instruc~oes testAndSet tem a atomicidade relativa a outras testAndSet
garantida pelo hardware;
boolean testAndSet(boolean lockState, boolean newLockState) faz lockState
= newLockState e retorna o valor antigo deste par^ametro
Codigo para travamento do nucleo:
while (testAndSet(lockState, true))fg
Codigo para destravamento do nucleo:
testAndSet(lockState, false)
(reparem no uso de espera ocupada)
63
3.0.5 Resumo e Conclus~oes
A reaca~o a interrupc~oes e feita em parte por hardware, e em parte por
software
Co-rotinas s~ao um bom meio de estruturar as mudancas de contexto que
ocorrem apos as interrupc~oes
Um nucleo simples de multiprogramac~ao utiliza uma co-rotina por processo criado, uma co-rotina para o processo pai, e uma co-rotina para o
proprio nucleo
A exclus~ao mutua no acesso ao nucleo e obtida por inibic~ao de interrupc~oes
3.0.6 Exerccios
Exerccio 3.0.1 (Sleep) Modique o nucleo da sec~ao 3 para implementar a
primitiva sleep(int nrofTicks) , que faz com que um processo pare de disputar o processador pelo numero de ticks especicado.
Exerccio 3.0.2 (Mensagens) Mensagens s~ao muitas vezes utilizadas para a
interac~ao entre processos. Modique o nucleo da sec~ao 3 de forma a implementar as primitivas send(Process dest, Message m) e receive(Process
source, Message m) . Implemente os modos sncrono, onde o processo que envia uma mensagem e bloqueado ate a sua recepc~ao, e assncrono, sem bloqueio
do remetente.
Exerccio 3.0.3 (Cobegin-Coend generalizado) Discuta a implementac~ao
de nveis arbitrarios de cobegin-coend.
Exerccio 3.0.4 (Fork-Join) Modique o nucleo da sec~ao 3 para implemen-
tar a funca~o fork(Process p) , que dispara o processo recem-criado p sem
interromper a execuc~ao do processo que faz o disparo, e a func~ao join(Process
p) , que bloqueia o processo que a executa at
e a morte do processo p .
Exerccio 3.0.5 (Controle da Multiplexac~ao) Acrescente ao nucleo dado
em aula os procedimentos stopRoundRobin() e startRoundRobin(int timeSlice)
para controlar a preempc~ao de processos por ocasi~ao das interrupc~oes de relogio.
Exerccio 3.0.6 (Mensagens Assncronas) Modique o nucleo de multipro-
gramac~ao dado em aula acrescentando primitivas para comunicac~ao assncrona
por mensagens.
64
~
CAPITULO 3. NUCLEOS
DE MULTIPROGRAMACAO
Cap
tulo 4
Introduc~ao a Programac~ao
Paralela em Java
4.1 Introduc~ao
4.1.1 O Fen^omeno Java
A Linguagem de Programac~ao Java
Segundo a Sun, Java e simples, neutra com relac~ao a arquiteturas, orientada a
objetos, portatil, distribuda, tem alto desempenho, e interpretada, multitarefa,
robusta, din^amica e segura
Java e compilada e interpretada:
Os bytecodes podem ser vistos como o codigo de maquina da JVM, a Java
Virtual Machine.
65
~ A PROGRAMACAO
~ PARALELA EM JAVA
66CAPITULO 4. INTRODUCAO
A Plataforma Java
Dois componentes:
a Java Virtual Machine (JVM)
a Java Application Programming Interface (Java API)
O que voc^e pode fazer em Java
programas (aplicac~oes)
applets
servidores
servlets
agentes
The core Java API
O Basico: Objetos, strings, threads, numeros, entrada/sada, estruturas de
dados, etc.
Applets: Convenc~oes usadas por applets
Rede: URLs, sockets, enderecos IP
Internacionalizac~ao: Ferramentas para produca~o de programas poliglotas
Seguranca: Assinaturas eletr^onicas, ger^encia de chaves publicas e privadas,
controle de acesso e certicados
Componentes: conhecidos como \Java Beans", podem se conectar a diversas
arquiteturas de componentes
Serializac~ao de Objetos: possibilita a transmiss~ao e a persist^encia de objetos, assim como a comunicac~ao via RMI (Remote Method Invocation)
Conectividade com Bancos de Dados: O uso de JDBC permite um acesso
uniforme a diversos bancos de dados
~
4.1. INTRODUCAO
67
Outras vantagens
Aprendizado facil
Codigo compacto (ate 4 vezes menor que C++)
Codigo de qualidade (sem coleta de lixo)
Desenvolvimento rapido
Independente de plataforma
Distribuic~ao e manutenc~ao centralizadas para applets
4.1.2 Hello World
Um passeio pelo tutorial da Sun: The "Hello World"Application1
4.1.3 Java n~ao tem pointers
Muito elegante, mas como e que eu implemento uma lista encadeada?
Veja os arquivos:
Makele2
TestFIFO.java3
FIFO.java4
FIFOElements.java5
E importante observar o uso do conceito de interface , o mecanismo de heranca
multipla de Java. No caso, foi implementada a interface java.util.Enumeration
, extremamente util para a escrita de loops.
4.1.4 Uma aplicac~ao real: Prj2tex
Esta e uma aplicac~ao que e utilizada no CENAPAD para produc~ao de relatorios
em Latex a partir de arquivos produzidos por scripts CGI, e do arquivo de
senhas.
Os arquivos que constituem a entrada do programa s~ao:
1
2
3
4
5
http://www.dcc.ufmg.br/javadoc/getStarted/application/index.html
http://www.dcc.ufmg.br/~vado/java/TestFIFO/Makele
http://www.dcc.ufmg.br/~vado/java/TestFIFO/TestFIFO.java
http://www.dcc.ufmg.br/~vado/java/TestFIFO/FIFO.java
http://www.dcc.ufmg.br/~vado/java/TestFIFO/FIFOElements.java
~ A PROGRAMACAO
~ PARALELA EM JAVA
68CAPITULO 4. INTRODUCAO
projetos.txt6
usuarios.txt7
passwd8
Os arquivos Java s~ao:
EmptyTokenStringTokenizer.java9
Projeto.java10
EntradaProjeto.java11
Projetos.java12
Login.java13
Usuario.java14
Logins.java15
Usuarios.java16
MinhaData.java17
Util.java18
Prj2tex.java19
4.2 Applets
4.2.1 Vis~ao Geral
Para incluir esta applet as linhas seguintes foram inseridas no meu arquivo latex:
6
7
8
9
10
11
12
13
14
15
16
17
18
19
http://www.dcc.ufmg.br/~vado/java/Prj2Tex/projetos.txt
http://www.dcc.ufmg.br/~vado/java/Prj2Tex/usuarios.txt
http://www.dcc.ufmg.br/~vado/java/Prj2Tex/passwd
http://www.dcc.ufmg.br/~vado/java/Prj2Tex/EmptyTokenStringTokenizer.java
http://www.dcc.ufmg.br/~vado/java/Prj2Tex/Projeto.java
http://www.dcc.ufmg.br/~vado/java/Prj2Tex/EntradaProjeto.java
http://www.dcc.ufmg.br/~vado/java/Prj2Tex/Projetos.java
http://www.dcc.ufmg.br/~vado/java/Prj2Tex/Login.java
http://www.dcc.ufmg.br/~vado/java/Prj2Tex/Usuario.java
http://www.dcc.ufmg.br/~vado/java/Prj2Tex/Logins.java
http://www.dcc.ufmg.br/~vado/java/Prj2Tex/Usuarios.java
http://www.dcc.ufmg.br/~vado/java/Prj2Tex/MinhaData.java
http://www.dcc.ufmg.br/~vado/java/Prj2Tex/Util.java
http://www.dcc.ufmg.br/~vado/java/Prj2Tex/Prj2tex.java
4.2. APPLETS
69
\begin{rawhtml}
<APPLET CODE= Simple.class
CODEBASE=//www.dcc.ufmg.br/~vado/java/Simple
WIDTH=500 HEIGHT=20>
</APPLET>
\end{rawhtml}
Uma applet reage a eventos no browser:
Evento
ao ser carregada, ou recarregada
ao ser visitada
ao deixar de ser visitada
ao ser descarregada, quando o browser e terminado, ou quando se aperta reload
Metodo
public void init()
public void start()
public void stop()
public void destroy()
Observac~oes
O metodo init() deve em geral conter o codigo que seria usado em um construtor
Applets em geral n~ao t^em construtores, pois o ambiente de execuc~ao so esta
completo quando init() e chamado
O metodo start() em geral e quem faz o trabalho da applet, ou que dispara
threads para faz^e-lo
O metodo stop() suspende a execuca~o da applet, de forma a liberar os recursos
utilizados enquanto o usuario n~ao v^e a applet.
O metodo destroy() e muitas vezes desnecessario, pois stop() ja faz todo o
trabalho de liberac~ao de recursos.
O metodo paint(Graphics
g)
A denic~ao da apar^encia de uma applet e feita atraves do metodo paint(Graphics
g).
O browser e quem chama paint, passando como par^ametro uma inst^ancia da
classe Graphics, que a applet usa para se desenhar.
No caso, o metodo usado e:
public void paint(Graphics g) {
//Draw a Rectangle around the applet's display area.
g.drawRect(0, 0,
getSize().width - 1,
~ A PROGRAMACAO
~ PARALELA EM JAVA
70CAPITULO 4. INTRODUCAO
getSize().height - 1);
//Draw the current string inside the rectangle.
g.drawString(buffer.toString(), 5, 15);
}
A applet pode induzir o browser a chamar o metodo paint, como em
void addItem(String newWord) {
System.out.println(newWord);
buffer.append(newWord);
repaint();
}
4.3 Eventos
Eventos s~ao o conceito essencial para a construc~ao de interfaces gracas.
Vamos aqui examinar o modelo de eventos da AWT 1.120 .
Eventos s~ao gerados por fontes de eventos: menus, bot~oes, etc.
Um ou mais listeners podem se registrar e ser noticados da ocorr^encia de
eventos de um determinado tipo oriundos de uma fonte particular.
Tratadores de eventos podem ser de qualquer classe, desde que implementem a
interface listener apropriada.
Em todo programa com tratadores de eventos trechos de codigo similares aos
seguintes est~ao presentes:
Na classe do tratador de eventos:
public class MyClass implements ActionListener {
O codigo que registra o listener:
someComponent.addActionListener(instanceOfMyClass);
O codigo do listener que reage ao evento:
public void actionPerformed(ActionEvent e) {
...//code that reacts to the action...
}
20
http://java.sun.com/docs/books/tutorial/ui/components/eventintro.html
4.4. THREADS
71
Beeper
O codigo desta applet esta aqui21 .
Comentarios:
uma applet e um container , e como tal pode receber componentes
atraves do metodo add
a disposic~ao dos componentes em um container e controlada por um
layout manager ; no caso, BorderLayout
cada layout manager tem a sua losoa de arranjo dos componentes
MultiListener
Este e um exemplo onde dois listeners atendem aos eventos de um mesmo componente.
Codigo:
MultiListener.java22
MouseEventDemo
Codigo:
MouseEventDemo.java23
BlankArea.java24
4.4 Threads
Aqui usei o seguinte codigo para incluir a applet:
\begin{rawhtml}
<CENTER>
<APPLET CODE= CardReaderApplet.class
ARCHIVE="CardReaderApplet.zip,progpar.zip"
WIDTH=500 HEIGHT=400>
</APPLET>
21
22
23
24
http://www.dcc.ufmg.br/~vado/java/Beeper/Beeper.java
http://www.dcc.ufmg.br/~vado/java/MultiListener/MultiListener.java
http://www.dcc.ufmg.br/~vado/java/MouseEventDemo/MouseEventDemo.java
http://www.dcc.ufmg.br/~vado/java/MouseEventDemo/BlankArea.java
~ A PROGRAMACAO
~ PARALELA EM JAVA
72CAPITULO 4. INTRODUCAO
</CENTER>
\end{rawhtml}
ilustrando outra maneira de indicar a fonte dos arquivos .class. Os arquivos
.zip foram produzidos atrav
es do comando
jar cvf file.zip *.class *.gif
no diretorio onde se encontram os arquivos .class e .gif. Os .zip resultantes
s~ao depois movidos para o mesmo diretorio onde se encontram as paginas html.
Os seguintes arquivos foram utilizados nesta applet:
CardReader.java25
UserProgram.java26
Buer.java27
CardReaderApplet.java28
: Observac~oes
CardReaderApplet.java
As threads s~ao criadas pelos comandos:
cardReaderThread =
new Thread(new CardReader(cardReaderPanel, buffer, MAXCARDS));
userProgramThread =
new Thread(new UserProgram(userProgramPanel,buffer,MAXCARDS));
usando o construtor Thread(Runnable runnable) que faz uso da interface Runnable, que exige que a classe implemente o metodo:
public void run()
: Observac~oes
Buffer.java
O ponto chave esta no uso de synchronized em metodos que s~ao executados
com exclus~ao mutua
Todo metodo synchronized de um objeto realiza, no incio de sua execuc~ao,
um lock em uma chave implcita associada ao objeto, e ao terminar realiza
um unlock sobre esta mesma chave;
25
26
27
28
http://www.dcc.ufmg.br/~vado/java/CardReaderApplet/CardReader.java
http://www.dcc.ufmg.br/~vado/java/CardReaderApplet/UserProgram.java
http://www.dcc.ufmg.br/~vado/java/CardReaderApplet/Buer.java
http://www.dcc.ufmg.br/~vado/java/CardReaderApplet/CardReaderApplet.java
4.4. THREADS
73
Existe tambem uma unica cama associada ao objeto; o metodo wait()
libera a chave do objeto, e coloca o processo que o executa dormindo
nesta cama;
Um processo que executa wait pode ser despertado
{ pela execuc~ao de notify() por um outro processo, ou
{ pela ocorr^encia de uma excec~ao (que tambem pode provocada por
outro processo)
A possibilidade de ocorr^encia da excec~ao forca o uso de try e catch
,
,
: Observac~oes
Consumer.java Producer.java Queue.java
Producer e Consumer t^em o metodo run(), e implementam a interface
Runnable
Ao serem criados, recebem uma area de texto
Atrasos rand^omicos s~ao impostos pelo metodo sleep ;
A classe Queue e uma PE SSIMA programac~ao de uma la em Java; a
biblioteca jgl (veja nos links) tem otimos exemplos de las e de outras
estruturas de dados.
Applet: leitores e escritores, soluc~ao injusta
Os seguintes arquivos foram usados na confec~ao desta applet:
Makele29
RWApplet.java30
RWScheduler.java31
Reader.java32
Writer.java33
29
30
31
32
33
http://www.dcc.ufmg.br/~vado/java/RWApplet/Makele
http://www.dcc.ufmg.br/~vado/java/RWApplet/RWApplet.java
http://www.dcc.ufmg.br/~vado/java/RWApplet/RWScheduler.java
http://www.dcc.ufmg.br/~vado/java/RWApplet/Reader.java
http://www.dcc.ufmg.br/~vado/java/RWApplet/Writer.java
~ A PROGRAMACAO
~ PARALELA EM JAVA
74CAPITULO 4. INTRODUCAO
RWApplet.java, Reader.java, Writer.java, RWScheduler.java
Esta applet cria threads pertencendo a dois ThreadGroups, de leitoras e
escritoras;
Quando o bot~ao start e apertado, as threads s~ao disparadas;
Quando o bot~ao stop e apertado, a applet termina (aqui certamente ela
pode ser melhorada)
Os processos leitores e escritores executam um loop (quase) eterno, com
esperas forcadas por sleep para ajudar na animac~ao
RWScheduler e uma implementac~ao direta do algoritmo da transpar^encia
2.4.3
Leitores e escritores: Applet para soluc~ao equ^anime
Os seguintes arquivos foram usados na confec~ao desta applet:
34
35
36
37
38
39
40
41
42
Makele34
FairRWApplet.java35
RWFairScheduler.java36
TicketQueue.java37
Request.java38
TimeComparator.java39
ValuePanel.java40
Reader.java41
Writer.java42
http://www.dcc.ufmg.br/~vado/java/FairRWApplet/Makele
http://www.dcc.ufmg.br/~vado/java/FairRWApplet/FairRWApplet.java
http://www.dcc.ufmg.br/~vado/java/FairRWApplet/RWFairScheduler.java
http://www.dcc.ufmg.br/~vado/java/FairRWApplet/TicketQueue.java
http://www.dcc.ufmg.br/~vado/java/FairRWApplet/Request.java
http://www.dcc.ufmg.br/~vado/java/FairRWApplet/TimeComparator.java
http://www.dcc.ufmg.br/~vado/java/FairRWApplet/ValuePanel.java
http://www.dcc.ufmg.br/~vado/java/FairRWApplet/Reader.java
http://www.dcc.ufmg.br/~vado/java/FairRWApplet/Writer.java
4.4. THREADS
75
Para usar a biblioteca jgl a seguinte linha deve ser acrescentada ao seu .cshrc:
A applet abaixo deveria ilustrar o comportamento de uma soluc~ao em Java
para este problema, incluindo ainda a tecnica de aging. N~ao sei por qual raz~ao
o Netscape 3.1 n~ao implementa interrupt() como o appletviewer do JDK, e
a applet se bloqueia.
Fontes:
Makele43
Client.java44
PrinterScheduler.java45
Request.java46
SJFApplet.java47
SJFQueue.java48
SizeComparator.java49
ValuePanel.java50
R recursos: Soluc~ao Java
Fontes:
43
44
45
46
47
48
49
50
51
52
53
54
55
Makele51
Client.java52
NResourcesScheduler.java53
Request.java54
NResourcesApplet.java55
http://www.dcc.ufmg.br/~vado/java/SJFApplet/Makele
http://www.dcc.ufmg.br/~vado/java/SJFApplet/Client.java
http://www.dcc.ufmg.br/~vado/java/SJFApplet/PrinterScheduler.java
http://www.dcc.ufmg.br/~vado/java/SJFApplet/Request.java
http://www.dcc.ufmg.br/~vado/java/SJFApplet/SJFApplet.java
http://www.dcc.ufmg.br/~vado/java/SJFApplet/SJFQueue.java
http://www.dcc.ufmg.br/~vado/java/SJFApplet/SizeComparator.java
http://www.dcc.ufmg.br/~vado/java/SJFApplet/ValuePanel.java
http://www.dcc.ufmg.br/~vado/java/NResourcesApplet/Makele
http://www.dcc.ufmg.br/~vado/java/NResourcesApplet/Client.java
http://www.dcc.ufmg.br/~vado/java/NResourcesApplet/NResourcesScheduler.java
http://www.dcc.ufmg.br/~vado/java/NResourcesApplet/Request.java
http://www.dcc.ufmg.br/~vado/java/NResourcesApplet/NResourcesApplet.java
~ A PROGRAMACAO
~ PARALELA EM JAVA
76CAPITULO 4. INTRODUCAO
NResourcesQueue.java56
SizeComparator.java57
ValuePanel.java58
R recursos: Justicativa
O processo cliente entra na la numa posic~ao dependente do instante em
que chega e do numero de recursos pedidos: mais recursos, pior prioridade.
Cada vez que um cliente em espera e preterido, sua prioridade aumenta,
e assim todo cliente com fome chega a comer.
O controle da exclus~ao mutua e feito atraves da la available .
setenv CLASSPATH .:/usr/local/java/lib:/usr/local/java/lib/jgl 2 0
4.5 Conclus~oes
56
57
58
http://www.dcc.ufmg.br/~vado/java/NResourcesApplet/NResourcesQueue.java
http://www.dcc.ufmg.br/~vado/java/NResourcesApplet/AgeComparator.java
http://www.dcc.ufmg.br/~vado/java/NResourcesApplet/ValuePanel.java
4.6. 1O TRABALHO PRATICO
77
4.6 1o Trabalho Pratico
Distribuic~ao: 19/10/98
Entrega:
09/11/98
Primeira parte : descobrir o que esta acontecendo com as minhas applets,
que est~ao se redesenhando a cada vez que se volta na pagina, explicar e propor
uma soluc~ao.
Segunda parte : Construa applets em Java para animar os algoritmos da
prova. Procure fazer uma visualizac~ao t~ao didatica quanto possvel, mas sem
fazer com que a interface torne obscura a codicac~ao original do algoritmo.
Utilize o mecanismo de prioridades de Java para implementar um metodo de
acordar seletivamente um determinado processo.
~ A PROGRAMACAO
~ PARALELA EM JAVA
78CAPITULO 4. INTRODUCAO
Cap
tulo 5
Outras Linguagens e
Notaco~es para Programac~ao
Paralela
Vamos nesta seca~o examinar diversas construc~oes e linguagens propostas para
a programac~ao paralela assncrona.
Algumas destas construc~oes, como as path expressions, caram em desuso; outras
s~ao ainda muito utilizadas, como os semaforos.
Vamos dedicar uma atenc~ao especial a linguagem CSP, pela grande inu^encia
que exerceu sobre a academia e a industria.
5.1 Especicac~ao de Execuc~ao em Paralelo
Cobegin / Coend
Fork / Join
Program P1;
...
fork(P2);
...
join(P2);
Program P2;
...
...
...
END
{ A execuc~ao de P2 e iniciada quando o fork em P1 e executado;
{ P1 e P2 executam em paralelo ate que P1 atinja o comando join
, ou ate que P2 termine;
79
~ PARA PROGRAMACAO
~ PARALELA
80CAPITULO 5. OUTRAS LINGUAGENS E NOTACOES
{ P1 so ultrapassa o comando join apos o termino de P2 ;
{ ferramenta pratica e poderosa, mas seu uso indisciplinado pode levar
a programas inextricaveis;
{ a variante Unix e (muito) utilizada para a criac~ao de processos pesados.
5.2 Sincronizac~ao com Memoria Compartilhada
A sincronizac~ao e obtida com o uso de um conjunto de operac~oes garantidamente at^omicas, que fazem parte da linguagem, ou s~ao adicionadas a
um ambiente de programac~ao sequencial;
Objetivos:
{ impedir a execuc~ao em paralelo de ac~oes conitantes, garantindo assim a denic~ao de uma sem^antica para programas paralelos;
{ racionalizar a utilizac~ao dos processadores.
5.2.1 Acessos Indivisveis a Memoria
Regras do jogo:
U nico conjunto de ac~oes at^omicas: leituras e escritas de palavras na
memoria;
N~ao existe possibilidade de implementac~ao de espera n~ao-ocupada;
A import^ancia pratica restringe-se a implementac~ao em hardware de mecanismos primitivos de exclus~ao mutua;
A import^ancia acad^emica e muito grande; Dijkstra[Dijkstra, 1965b], Knuth[Knuth, 1966]
e diversos outros cientistas de calibre ja se ocuparam do problema da obtenc~ao da exclus~ao mutua nestas condic~oes;
A primeira soluc~ao deve-se ao matematico holand^es Dekker, e foi publicada
por Dijkstra [Dijkstra, 1965a] em 1968.
Algoritmo de Dekker, simplicado por Peterson
PROGRAM DekkerPeterson;
VAR need: ARRAY[1..2] OF BOOLEAN;
turn: 1..2;
~ COM MEMORIA
5.2. SINCRONIZACAO
COMPARTILHADA
81
COBEGIN
P1:: LOOP
VAR need1: BOOLEAN;
turn1: 1..2;
/* locais ao processo P1 */
...
/* Protocolo de entrada */
< need[1] := TRUE >
< turn
:= 2
>
/* <..> eh atomico */
REPEAT
< need1 := need[2] >;
< turn1 := turn
>;
UNTIL (NOT need1) OR (turn1 = 1);
/* regiao critica */
...
/* Protocolo de saida */
< need[1] := FALSE >;
...
END;
//
P2:: LOOP
/* codigo simetrico */
END;
Este e possivelmente o algoritmo mais complexo deste curso; sua correc~ao n~ao
deve ser aceita sem o uso de tecnicas formais.
5.2.2 Semaforos
Introduzidos por Dijkstra em 1968[Dijkstra, 1965a];
S~ao inteiros n~ao negativos com as operac~oes:
P(s) se s for maior do que zero, s e decrementado em uma operac~ao
at^omica ; caso contrario, atrasa o processo que a executa ate que s
seja maior que 0;
V(s) incrementa s em uma operac~ao at^omica.
e V s~ao as iniciais de Proberen e de Verhogen, palavras em holand^es
que querem dizer tentar e incrementar
P
P e V s~a tambem chamadas wait e signal , ou up e down ;
existem implementac~oes tanto com espera-ocupada como com liberac~ao
do processador.
~ PARA PROGRAMACAO
~ PARALELA
82CAPITULO 5. OUTRAS LINGUAGENS E NOTACOES
Semaforos em Java
public class Semaphore {
int value;
public Semaphore(int initialValue){
value = initialValue;
}
public synchronized void P() {
while (value <= 0 ) {
try {
wait();
catch(InterruptedException e){}
}
value--;
}
public synchronized void V() {
p++;
notify();
}
}
Exclus~ao Mutua com Semaforos
Semaphore
semaphore = new SEMAPHORE(1);
COBEGIN
P1:: LOOP
...
semaphore.P();
/* secao critica */
semaphore.V();
...
END;
//
P2:: LOOP
...
semaphore.P();
/* secao critica */
semaphore.V();
...
END;
COEND
semaforos que so assumem os valores 0 e 1 s~ao conhecidos como semaforos
~ COM MEMORIA
5.2. SINCRONIZACAO
COMPARTILHADA
83
binarios ;
os outros s~ao chamados de semaforos gerais , ou semaforos contadores .
Produtor/Consumidor com semaforos
O semaforo cheios conta as posic~oes ocupadas no buer;
O semaforo vazios conta as posic~oes vazias.
class Buffer{
int p=0, c=0;
Semaphore cheios = new Semaphore(0);
Semaphore vazios = new Semaphore(MAX);
public void put(char x) {
vazios.P();
buf[p] = x;
p = (p + 1) % MAX;
cheios.V();
}
public char get() {
cheios.P();
char x = Buf[c];
c := (c + 1) MOD (MAX + 1);
vazios.V();
return x;
}}
O paralelismo e maior, pois partes distintas do buer s~ao acessadas simultaneamente;
A complexidade da soluc~ao e maior.
~ PARA PROGRAMACAO
~ PARALELA
84CAPITULO 5. OUTRAS LINGUAGENS E NOTACOES
Jantar dos Filosofos
Provavelmente o mais famoso dos problemas classicos de sincronizac~ao:
Cinco losofos est~ao em uma mesa; no centro desta mesa esta um prato
de espaguete.
Existem cinco garfos, dispostos na mesa de forma a que cada losofo compartilha um garfo com cada um de seus dois vizinhos
Cada losofo tem um comportamento cclico:
{ pensa;
{ tem fome;
{ come;
{ volta a pensar.
Um losofo faminto precisa dos dois garfos que compartilha com seus
vizinhos para se servir.
Uma soluc~ao deve implementar a exclus~ao mutua no uso dos garfos e
impedir a formac~ao de ciclos de espera gerando deadlocks.
~ COM MEMORIA
5.2. SINCRONIZACAO
COMPARTILHADA
Soluc~ao com Semaforos { 1
Soluc~ao do Tanembaum ([Tanenbaum, 1987]):
#define N
#define LEFT
#define RIGHT
5
(i-1)%N
(i+1)%N
int state[N];
SEMAPHORE mutex = 1;
SEMAPHORE s[N]; /* todos iguais a zero inicialmente */
void philosopher(int i) {
while (TRUE) {
think();
take_forks(i);
eat();
put_forks(i);
}
}
Soluc~ao com Semaforos { 2
void take_forks (int i) {
down(mutex); /* exclusao mutua nas variaveis de controle */
state[i] = HUNGRY;
test(i);
up(mutex);
down(s[i]);
/* exclusao mutua com vizinhos */
}
void test(int i) {
if (state[i] == HUNGRY &&
state[LEFT] != EATING && state[RIGHT] != EATING) {
state[i] = EATING;
up(s[i]);
};
/*
}
void put_forks(int i) {
down(mutex); /* exclusao mutua nas variaveis de controle */
state[i] = THINKING;
85
~ PARA PROGRAMACAO
~ PARALELA
86CAPITULO 5. OUTRAS LINGUAGENS E NOTACOES
test(LEFT); // notifica
test(RIGHT);// os vizinhos
up(mutex);
}
5.2.3 Monitores
Sugeridos por Hoare[Hoare, 1974] e Brinch-Hansen[Hansen, 1972] por vol-
ta de 1972 como meio de encapsular numa unica estrutura sintatica todos
os comandos relativos a uma mesma estrutura de dados;
E a ideia de modulo associada a exclus~ao mutua implcita no uso
de seus procedimentos publicos;
As propostas para monitores diferem nas ferramentas oferecidas para espera por condic~oes favoraveis, e na maneira como processos suspensos s~ao
reativados.
Uma classe Java com todos os metodos synchronized e um monitor.
Monitores: Proposta de Hoare
Processos s~ao atrasados em condition variables ;
Sobre uma condition variable s~ao denidas as operac~oes de
e signal ;
A execuc~ao de
cond.signal
wait
por um processo P tem como efeito:
{ se nenhum processo estiver bloqueado em cond , P prossegue nor-
malmente;
{ sen~ao, um dos processos bloqueados e escolhido para prosseguir,
e P e atrasado ate que este processo libere o monitor;
{ faz parte da denic~ao que a escolha do acordado n~ao e sujeita a
\starvation";
{ acordadores t^em prioridade sobre os novatos na tomada do monitor.
Monitores: Proposta de Brinch-Hansen
Processos s~ao atrasados em variaveis do tipo queue ;
Operac~oes associadas: delay e continue .
A execuc~ao de continue por um processo implica na sua sada do
monitor, cuja posse e transmitida ao processo acordado;
~ COM MEMORIA
5.2. SINCRONIZACAO
COMPARTILHADA
87
Cada variavel do tipo queue so pode abrigar um unico processo, o que
leva a um uso frequente de vetores de
mentac~ao.
queue
s, mas simplica a imple-
Inconvenientes das propostas de Hoare e Brinch-Hansen:
signal ou continue deve ser um ponto de consist^encia do monitor;
a reativac~ao de mutiplos processos so pode ser feita por meios indiretos,
e e de difcil coordenac~ao.
5.2.4 \Path Expressions" { 1
Proposic~ao: Campbell e Habermann[Campbell and Habermann, 1974]
Ideia: por um unico comando, da forma path (path list) end , pro
gramar explicitamente todas as restric~oes na execuc~ao das operac~oes do
modulo;
N~ao existem outros meios de sincronizac~ao;
O uso e vantajoso quando a especicac~ao natural de um modulo e feita
em termos de historias admissveis de suas operac~oes, e desvantajoso no
caso contrario;
Linguagens: COSY, PATH PASCAL;
Operadores:
,
;
n:(<path list>)
[<path list>]
concorr^encia
sequenciamento
ate n ativac~oes da <path list>
numero n~ao limitado de ativac~oes
\Path Expressions" { 2
path deposit , fetch end
{ n~ao imp~oe restric~oes nem na ordem de execuc~ao das operac~oes de
deposit
e fetch , nem no numero de ativac~oes;
path deposit; fetch end
{ todo fetch deve ser precedido de deposit ;
{ o numero de fetch s ativos ou completos n~ao pode exceder o numero
de deposit s completos;
~ PARA PROGRAMACAO
~ PARALELA
88CAPITULO 5. OUTRAS LINGUAGENS E NOTACOES
path 1:
{
n:
(deposit; fetch) end
deposit
(1:
e fetch se alternam e s~ao mutuamente exclusivas;
(deposit) ; 1:
(fetch) ) end
{ as ativac~oes de deposit , assim como as de fetch , s~ao mutuamente
exclusivas;
{ cada ativac~ao de fetch e precedida por um deposit completo;
{ a diferenca entre o numero de deposit s completos e o numero de
fetch s ativos nunca e maior que n ;
1:
( [read] ; write ) end
{ soluc~ao para leitores e escritores.
5.2.5 Mensagens
No modelo \puro", a unica interac~ao permitida e a troca de mensagens;
As variaveis de um processo s~ao de acesso exclusivo;
A atomicidade de operac~oes do tipo send(destination, msg) e receive(source,
e garantida;
Variac~oes dependem
{ do esquema de buerizac~ao, e
{ do esquema de designac~ao de destinos e fontes;
A grande vantagem esta na facil utilizaca~o em ambientes distribudos;
msg)
Produtor/Consumidor com Mensagens
Exemplo do Tanembaum ([Tanenbaum, 1987])
#define N 100
void producer (void) {
char item; message m;
while (TRUE) {
produce_item(&item);
receive(consumer, &m); /* espera por msg vazia */
build_message(&m, item);
send(consumer, m);
}
}
5.3. CSP { COMMUNICATING SEQUENTIAL PROCESSES
89
void consumer (void) {
char item; int i; message m;
/* producao inicial de mensagens vazias */
for (i = 0; i < N; i++) send(producer, m);
/* regime */
while (TRUE) {
receive(producer, &m);
extract_item(m, &item);
consume_item(item);
send(producer, m);
}
}
Tem-se um maximo de N mensagens em tr^ansito.
5.2.6 Conclus~oes
Existem muitas construc~oes para programac~ao paralela (nesta
aula so vimos algumas; propostas importantes como Linda ou
Erlang n~ao foram examinadas)
Java adota monitores (classe com metodos synchronized) e fork
(new Thread, start() )
Mensagens s~ao muito utilizadas, e nos ocuparemos muito delas
na sec~ao8 .
5.3 CSP { Communicating Sequential Processes
Pseudo-linguagem proposta por Hoare em 1978; aqui seguimos elmente o artigo Communicating Sequential Processes [Hoare, 1978]
Proposta de estudo e estruturac~ao de construc~oes lingusticas para:
{ entrada e sada
{ express~ao de paralelismo
{ sincronizac~ao de processos
Uso de comandos guardados da forma condic~ao ! ac~ao , para
controle sequencial e express~ao de n~ao-determinismo;
~ PARA PROGRAMACAO
~ PARALELA
90CAPITULO 5. OUTRAS LINGUAGENS E NOTACOES
Comando paralelo baseado em cobegin ... coend; processos paralelos n~ao compartilham variaveis ;
A comunicac~ao entre processos concorrentes e feita por comandos simples de entrada e sada ;
Comandos de entrada e sada devem se casar : o valor de sada e copiado
de um processo para o outro;
Um comando de entrada ou de sada e atrasado ate que o outro
processo esteja pronto para a execuca~o do comando de sada ou de
entrada correspondente;
Comandos de entrada podem aparecer em guardas;
N~ao e uma linguagem completa : faltam regras para denic~ao de
dados, recursividade, etc.
5.3.1 Conceitos e Notac~oes
BNF:
<command> ::= <simple command> |
<structured command>
<simple command> ::= <null command> |
<assignment command> |
<input command> |
<output command >
<structured command> ::= <alternative command> |
<repetitive command> |
<parallel command>
<null command> ::= skip
<command list> ::= {<declaration>; |<command>;} <command>
chaves indicam zero ou mais repetic~oes;
um comando pode ser bem sucedido ou falhar;
um comando nulo n~ao tem nenhum efeito, e nunca falha;
uma lista de comandos especica execuc~ao sequencial;
cada declarac~ao introduz novas variaveis, cujo escopo vai ate o m da lista.
5.3. CSP { COMMUNICATING SEQUENTIAL PROCESSES
91
Comandos Paralelos
<parallel command> ::= [<process> {//<process>}]
<process> ::= <process label> <command list>
<process label> ::= <empty> |
<identifier> :: |
<identifier> (<label subscript>
{,<label subscript>}
) ::
<label subscript> ::= <integer constant> | <range>
<integer constant> ::= <numeral> | <bound variable>
<bound variable> ::= <identifier>
<range> ::= <bound variable> : <lower bound>..<upper bound>
<lower bound> ::= <integer constant>
<upper bound> ::= <integer constant>
os processos de um comando paralelo devem ser disjuntos ;
ZeraX(i:1..2):: X(i) := 0 e equivalente a
ZeraX(1):: X(1) := 0 // ZeraX(2):: X(2) := 0.
Comandos Paralelos { Exemplos
Exemplo 1:
[
cardreader ? cardimage
//
lineprinter ! lineimage
]
Obs.: \?" e a recepc~ao de uma mensagem; \!" e o envio de uma mensagem.
Exemplo 2:
~ PARA PROGRAMACAO
~ PARALELA
92CAPITULO 5. OUTRAS LINGUAGENS E NOTACOES
[
west:: DISASSEMBLE
//
X:: SQUASH
//
east:: ASSEMBLE
]
palavras em maiusculas s~ao \macros" { listas de comandos a serem expandidas
Exemplo 3:
[
room :: ROOM
//
fork(i:0..4):: FORK
//
phil(i:0..4):: PHIL
]
este comando paralelo dene 11 processos. O comportamento de fork(1),
fork(2), etc. e especicado pela lista de comandos FORK, aonde
i
e utilizada para identicar cada fork(i).
a variavel
Comandos de Atribuic~ao - BNF
<assignement command> ::= <target variable> := <expression>
<expression> ::= <simple expression> |
<structured expression>
<structured expression> ::= <constructor>(<expression list>)
<constructor> ::= <empty> |
<identifier>
<expression list> ::= <empty> |
<expression> {, <expression>}
<target variable> ::= <simple variable> |
<structured target>
5.3. CSP { COMMUNICATING SEQUENTIAL PROCESSES
<structured target> ::= <constructor>
(<target variable list>)
<target variable list> ::= <empty> |
<target variable>
{, <target variable> }
Comandos de atribuic~ao: Exemplos
Exemplo 1
x := x + 1
Exemplo 2
(x , y) := (y , x)
troca x com y, usando construtores vazios;
Exemplo 3
x := cons(left, right)
x recebe um valor estruturado pelo construtor cons;
Exemplo 4
cons(left,right) := x
falha se x n~ao tem a forma cons(y,z);
Exemplo 5
insert(n) := insert(2*x + 1)
equivalente a n
Exemplo 6
:= 2*x + 1
93
~ PARA PROGRAMACAO
~ PARALELA
94CAPITULO 5. OUTRAS LINGUAGENS E NOTACOES
c := P()
atribui a c um \sinal" com construtor P e sem componentes;
Exemplo 7
P() := c
falha se o valor de c n~ao e P(); n~ao tem nenhum efeito nos outros casos;
Exemplo 8
insert(n) := has(n)
falha sempre.
Comandos de Entrada e de Sada: rendez-vous
<input command>
::=
<source> ? <target variable>
<output command> ::= <destination> ! <expression>
<source>
::= <process name>
<destination> ::= <process name>
<process name> ::= <identifier> |
<identifier> (<subscripts>)
<subscripts> ::= <integer expression>
{,<integer expression>}
ocorre comunicac~ao entre dois processos paralelos quando:
1. um comando de entrada num processo especica o outro
como fonte ;
2. um comando de sada no outro processo especica o primeiro
como destino ;
3. a variavel alvo do comando de entrada casa-se com o valor
da express~ao de sada ;
os comandos casados s~ao executados simultaneamente, e o seu
efeito combinado e o de um comando de atribuic~ao da express~ao
de sada para a variavel alvo .
este tipo de sincronizaca~o e conhecido como rendez-vous - encontro,
em franc^es.
5.3. CSP { COMMUNICATING SEQUENTIAL PROCESSES
95
Comandos de Entrada e de Sada: Exemplos
Exemplo 1: a variavel cardimage e atribudo o valor de uma express~ao do
mesmo tipo enviada pelo processo cardreader
cardreader ? cardimage
Exemplo 2: transmiss~ao de lineimage para o processo lineprinter
lineprinter ! lineimage
Exemplo 3
X ? (x,y)
o comando de sada correspondente deve enviar uma express~ao formada
por dois valores agrupados por um construtor vazio;
Exemplo 4
DIV ! (3*a + b, 13)
Exemplo 5
console(i) ? c
Exemplo 6
console(j-1) ! "A"
Exemplo 7
X(i) ? V()
Exemplo 8
sem ! P()
Comandos Alternativos e Repetitivos: Sintaxe
<repetitive command> ::= *<alternative command>
~ PARA PROGRAMACAO
~ PARALELA
96CAPITULO 5. OUTRAS LINGUAGENS E NOTACOES
<alternative command> ::= [<guarded command>
{|| guarded command>}]
<guarded command> ::= <guard> -> <command list> |
<range list>
<guard> -> <command list>
<guard> ::= <guard list>|
<guard list> ; <input command> |
<input command>
<guard list> ::= <guard element> {; <guard element>}
<guard element> ::= <boolean expression> |
<declaration>
Comandos Alternativos e Repetitivos: Caractersticas
um comando alternativo especica a execuc~ao de exatamente uma
de suas clausulas;
se todas as clausulas falham, o comando alternativo falha;
a escolha de uma clausula dentre as habilitadas e n~ao-determinstica
.
um comando repetitivo especica a execuc~ao repetida do comando
alternativo correspondente ate que este falhe;
quando todas as guardas falham, o comando repetitivo n~ao tem efeito.
um comando alternativo em que todas as guardas incluem um comando
de entrada sera atrasado ate que
1. um comando de sada que se case com uma das guardas de entrada
seja executado, ou
2. todas as fontes tenham terminado.
Comandos Alternativos e Repetitivos: Exemplos { 1
Exemplo 1
[
x >= y -> m := x
||
5.3. CSP { COMMUNICATING SEQUENTIAL PROCESSES
97
y >= x -> m := y
]
Exemplo 2
i := 0;
*[
i < size; content(i) <> n -> i := i + 1
]
Exemplo 3
*[
c: character;
west ? c -> east ! c
]
Exemplo 4
*[
(i:1..10)
continue(i);
console(i) ? c
-> X ! (i,c);
console(i) ! ack();
continue(i) := (c <> sign off)
]
Comandos Alternativos e Repetitivos: Exemplos { 2
Exemplo 5
*[
n: integer;
X ? insert(n) -> INSERT
||
X ? has(n)
-> SEARCH;
X ! (i < size)
]
a escolha entre estas duas alternativas e determinada pelo primeiro comando de X onde um inteiro e enviado com o construtor insert ou com
o construtor has;
~ PARA PROGRAMACAO
~ PARALELA
98CAPITULO 5. OUTRAS LINGUAGENS E NOTACOES
Exemplo 6
*[
X ? V()
-> val := val + 1
||
val > 0;
Y ? P() -> val := val - 1
]
5.3.2 Exemplos de Uso
Co-rotinas
Co-rotinas s~ao vistas aqui essencialmente como processos servidores, que recebem demandas e executam um servico.
COPY:
X :: *[ c: character; west ? c -> east ! c ]
SQUASH:
X :: *[
c: character;
west ? c ->
[ c <> asterisk -> east ! c;
|| c = asterisk ->
west ? c;
[ c <> asterisk -> east ! asterisk;
east ! c
|| c = asterisk -> east ! uparrow
]
]
]
DISASSEMBLE:
*[cardimage: (1..80) character;
cardfile ? cardimage ->
i: integer; i := 1;
*[i <= 80 -> X ! cardimage(i); i := i + 1 ];
X ! space
]
Co-rotinas { 2
ASSEMBLE:
5.3. CSP { COMMUNICATING SEQUENTIAL PROCESSES
99
lineimage: (1..125) character;
i: integer; i := 1;
*[
c: character;
X ? c ->
lineimage(i) := c;
[
i <= 124 -> i := i + 1;
||
i = 125 -> lineprinter ! lineimage;
i := 1
]
]
[
i = 1 -> skip
||
i > 1 -> *[
i <= 125 -> lineimage(i) := space;
i := i + 1
];
lineprinter ! lineimage
]
Linhas de montagem:
[ west:: DISASSEMBLE // X:: COPY // east:: ASSEMBLE ]
ou
[ west:: DISASSEMBLE // X:: SQUASH // east:: ASSEMBLE ]
Subrotinas
Uma subrotina pode ser implementada por uma co-rotina se todos os seus parametros s~ao passados por valor e por resultado:
[
subr:: *[
client ? (value parameters) ->
... ;
X ! (result parameters)
]
//
client:: *[
...
subr ! (arguments);
~ PARA PROGRAMACAO
~ PARALELA
100CAPITULO 5. OUTRAS LINGUAGENS E NOTACOES
...
subr ? (results)
...
]
]
Obs.: n~ao ha recursividade;
Divis~ao com Resto
[
DIV:: *[
x,y: integer;
X ? (x,y) ->
quot, rem: integer;
quot := 0;
rem := x;
*[
rem >= y -> rem := rem - y;
quot := quot + 1
];
X!(quot, rem)
]
//
X:: USER
]
Recursividade: Fatorial
[
fac(i:1..limit)::
*[
n: integer;
fac(i-1) ? n ->
[
n = 0 -> fac(i-1) ! 1
||
n > 0 -> fac(i+1) ! n-1;
r: integer;
fac(i+1) ? r;
fac(i-1) ! n*r
]
]
//
fac(0):: USER
5.3. CSP { COMMUNICATING SEQUENTIAL PROCESSES
]
Pesquisa e Inserc~ao Sequencial
[
S:: content: (0..99)integer;
size: integer;
size := 0;
*[
n: integer;
X ? has(n) -> SEARCH;
X!(i < size)
||
X ? insert(n) ->
SEARCH;
[
i < size
-> skip
||
i = size; size < 100 ->
content(size) := n;
size := size + 1
]
]
//
X:: *[...
S ! insert(n);
...
S ! has(k); ... S ? b
]
]
Pesquisa e Inserc~ao em Paralelo
[
S(i:1..100)::
*[
n: integer;
S(i-1) ? has(n) -> S(0)!false
||
S(i-1) ? insert(n) ->
*[
m: integer;
S(i-1) ? has(m) ->
[ m <= n -> S(0) ! (m = n)
|| m > n -> S(i+1) ! has(m)
101
~ PARA PROGRAMACAO
~ PARALELA
102CAPITULO 5. OUTRAS LINGUAGENS E NOTACOES
]
||
S(i-1) ? insert(m) ->
[ m < n -> S(i+1) ! insert(n);
n := m
|| m = n -> skip
|| m > n -> S(i+1) ! insert(m)
]
]
]
//
X:: *[ ...
S(1) ! insert(i); S(1) ! insert(j);
...
S(1) ! has(k);
...
[(i:1..100)S(i)?b -> skip];
]
]
Buer Limitado
X:: buffer: (0..9)portion;
in, out: integer;
in := 0; out := 0;
comment 0 <= out <= in <= out + 10
*[
in < out + 10;
producer ? buffer(in MOD 10) -> in := in + 1
||
out N in;
consumer ? more() ->
consumer ! buffer(out MOD 10);
out := out + 1
]
Semaforos
S:: val: integer;
val := 0;
*[
(i:1..100) X(i) ? V() -> val := val + 1
||
(i:1..100) val > 0;
X(i) ? P() -> val := val - 1
]
5.3. CSP { COMMUNICATING SEQUENTIAL PROCESSES
103
Filosofos
PHIL =
*[ ...
THINK;
room ! enter();
fork(RIGHT) ! pickup();
fork(LEFT) ! pickup();
EAT;
fork(RIGHT) ! putdown();
fork(LEFT) ! putdown();
room ! exit();
]
FORK =
*[
phil(LEFT) ? pickup() -> phil(LEFT) ? putdown()
||
phil(RIGHT)? pickup() -> phil(RIGHT)? putdown()
]
ROOM =
n: integer; n := 0;
*[
(i:0..4) n < 4; phil(i) ? enter() -> n := n+1
||
(i:0..4) phil(i) ? exit() -> n := n-1;
]
Filosofos:
[ room:: ROOM // fork(i:0..4) FORK // phil(i:0..4) PHIL ]
5.3.3 Notas
Esta vers~ao de CSP foi publicada em 1978, epoca em que o paralelismo
efetivo era essencialmente experimental;
O artigo e considerado como um dos mais inuentes da Ci^encia da Computac~ao, tendo inspirado desenvolvimentos praticos, como a linguagem
OCCAM e a arquitetura dos Transputers, e teoricos, como CCS (Calculus
of Communicating Systems), proposto por Milner[Milner, 1984]
~ PARA PROGRAMACAO
~ PARALELA
104CAPITULO 5. OUTRAS LINGUAGENS E NOTACOES
Exerccios
Exerccio 5.3.1 (Uso de Semaforos) Use semaforos para implementar lock(), unlock(), wait() e wakeup().
Parte II
Formulac~ao e Prova de
Propriedades de Programas
Paralelos
105
Cap
tulo 6
Modelos Formais para
Programas Paralelos
Fontes: [Keller, 1976],[Shankar, 1993]
Enfoques para a analise e especicac~ao:
{ asserc~oes baseadas em logica temporal
{ calculos de Milner (CCS, CSP)
Enfoque adotado: logica temporal
Precursores:
{ Floyd [Floyd, 1967]: asserc~oes sobre programas sequenciais
{ Hoare [Hoare, 1969]: formalizac~ao como uma logica
{ Dijkstra [Dijkstra, 1975]: comandos guardados
{ Pnueli[Pnueli, 1979], Manna e Pnueli[Manna and Pnueli, 1981]: logica
temporal
{ Owick e Gries[Owick and Gries, 1976]: n~ao interfer^encia
Propriedades de invari^ancia e de progresso
Safety (invariance) assertions : uma coisa ruim nunca acontece
{ se o programa termina, seus resultados est~ao corretos
{ o numero de lugares reservados num v^oo e menor ou igual ao total
de assentos no avi~ao (sem \over-booking")
{ n~ao existem impasses (\deadlocks")
107
108CAPITULO 6. MODELOS FORMAIS PARA PROGRAMAS PARALELOS
Progress (liveness) assertions : uma coisa boa sempre acontece
{ um programa sempre termina
{ toda demanda e satisfeita num tempo nito
Motivac~ao
Argumentac~ao por asserc~oes: mais do que um sistema formal de prova
Linguagem conveniente para descric~ao sem ambiguidades de propriedades
de sistemas concorrentes
Objetivos do topico:
{ propiciar familiaridade com a tecnica de argumentac~ao por asserc~oes
que possa ser aplicada a sistemas concorrentes e distribudos
{ consolidar a compreens~ao de programas paralelos, aumentando o
nvel de complexidade das soluco~es estudadas
6.0.1 O Buer Compartilhado
Codigo Java Simplicado
class Buffer {
private Queue buffer;
int n;
final int MAX = 10;
public Buffer() {
buffer = new Queue(MAX); n = 0;
}
public synchronized void put(char x) {
while(n >= MAX) {
wait();
}
buffer.append(x); n++;
notify();
}
public synchronized char get() {
while (n <= 0){
wait();
}
notify(); n--;
return buffer.dequeue();
}
}
109
Propriedades do Buer Compartilhado
A sequ^encia de caracteres consumidos e um prexo da sequ^encia
de caracteres produzidos.
{ \Prova": todo caracter produzido e colocado no m de uma lista
fo. Esta mesma lista e usada pelo consumidor para a retirada de
caracteres.
Todo caracter produzido e consumido ao m de um tempo nito.
{ \Prova": esta propriedade so se verica se
o processo consumidor sempre voltar a chamar o procedimento
get()
a administrac,a o da la associada ao synchronized for justa
Com estas hipoteses adicionais, a propriedade e obvia.
Propriedades Formais
Abordagem da Logica Temporal :
{ transformar um algoritmo em um objeto matematico formal
{ expressar e provar formalmente propriedades destes objetos
Inconveniente : dist^ancia entre o objeto formal e o algoritmo real (a di-
minuic~ao desta dist^ancia e um objetivo fundamental do projeto de linguagens de programac~ao paralela, e deve sempre fazer parte das preocupac~oes
do programador)
Vantagens :
{ express~ao e prova de propriedades sem ambiguidades
{ possibilidade de automaca~o da vericac~ao
Objeto formal:
{ conjuntos de estados
{ transico~es de estado
{ espaco de computac~oes
As propriedades de um algoritmo s~ao as propriedades de seu espaco de
computac~oes
110CAPITULO 6. MODELOS FORMAIS PARA PROGRAMAS PARALELOS
Sistemas de Transic~oes de Estados
Um sistema de transic~oes T e uma tripla T = (Q; ;; q0 ) onde
{ Q e um conjunto de estados - conjunto dos possveis valores
assumidos pelas variaveis estaticas do algoritmo
{ ; e um conjunto de comandos guardados
{ q0 2 Q e um estado inicial.
Um comando guardado 2 ; e um par = (g; a), onde
{ g : Q ! ftrue; falseg e uma func~ao que tem como par^ametro um
elemento de Q e como resultado true ou false; e uma guarda que
habilita ou desabilita o comando
{ a : Q ! Q e uma ac~ao que transforma o estado do sistema.
Todo sistema de transic~oes contem obrigatoriamente o comando guardado
nop = (true; identity), que sempre pode ser executado mas n~ao altera o
estado do sistema.
Computaco~es de um Sistema de Transic~oes
Uma computac~ao de um sistema de transic~oes T e uma sequ^encia
= [q0 ; 0 ]; [q1 ; 1 ]; : : : ; [qm ; m ]
em (Q;) (conjunto de sequ^encias no alfabeto formado por pares (estado,
comando guardado)) tal que
1. q0 e o estado inicial de T
2. 8k; 0 k < m, se k = (g; a) ent~ao g(qk ) = true e qk+1 = a(qk )
Em outras palavras, uma computaca~o deve
{ comecar pelo estado inicial, e
{ prolongar-se atraves das ac~oes de comandos com a guarda habilitada
pelo estado corrente;
Buer: Estados e Estado Inicial
O conjunto Q de estados e determinado pelas variaveis na seguinte tabela:
Variavel
consumerState
producerState
buer
n
product
consumption
Valores
fthinking, hungry g
fthinking, hungry g
char
int
char
char
Valor Inicial
thinking
thinking
0
111
Buer: Comandos Guardados
Com Guarda
1
consumerState = thinking
2
consumerState = hungry ^ n > 0
3
4
|Ac~ao
|consumerState = hungry;
|consumption = buer.head();
buer = buer.tail(); n = n - 1;
consumerState = thinking;
producerState = thinking
|producerState = hungry; product = randomChar();
producerState = hungry ^ n < MAX |buer.append(product); n = n
+ 1; producerState = thinking;
a execuc~ao dos comandos guardados se da de forma
{ n~ao-determinstica : qualquer comando com a guarda valida pode
ser selecionado para prolongar uma computac~ao e
{ at^omica : a ac~ao do comando selecionado e executada completamente, sem a interfer^encia de qualquer outra ac~ao
a transformac~ao do algoritmo inicial foi feita baseando-se nos pontos em
que a exclus~ao mutua e levantada:
{ no m dos procedimentos
{ nos comandos wait()
Buer: Uma computac~ao
Exemplo de computac~ao:
\Instante":
0
1 2
3
Habilitados: 1 , 3 3 4 2 , 3
Escolhido: 1 3 4 2
6.0.2 Invariantes
Um predicado de estado e uma func~ao
P : Q ! ftrue; falseg
Um invariante de uma computac~ao e um predicado de estado que
e valido em todos os seus estados;
Um invariante de um sistema de transic~oes e um invariante de
todas as suas computac~oes.
112CAPITULO 6. MODELOS FORMAIS PARA PROGRAMAS PARALELOS
Prova de Invari^ancia
Prova-se a invari^ancia de um predicado P de estado por induc~ao:
{ Base: provar que P e invariante para computac~oes de tamanho 1;
{ Induca~o: supondo que P e invariante para toda computac~ao de tamanho n, provar que P e invariante para toda computac~ao de tamanho
n + 1.
Em outras palavras:
{ Base: provar P (q0);
{ Induca~o: para todo comando guardado = (g; a), mostrar que
8q; q0 2 Q; q0 = a(q); P (q) ^ g(q) =) P (q0 )
(6.1)
(Obs.: ^ e a notac~ao para o \e" logico, e _ para o \ou".)
Ou: uma computac~ao so pode ser prolongada por um comando cuja guarda
e valida, e so precisamos considerar prolongamentos de computac~oes P invariantes.
Buer: invari^ancia de P 0 n MAX
Claramente P (q0 ) = true, pois n = 0 inicialmente;
E preciso agora varrer todos os comandos guardados, mostrando para cada
um deles que se P for valido, e se a guarda do comando for valida, o estado
resultante q0 tambem obedecera P .
Comando Prova
1 e 3
Para estes comandos, n0 = n, e a tese de
induc~ao (P (q0 )) se verica trivialmente;
2
Temos n > 0 (guarda), e 0 n MAX (hipotese de induc~ao). Como
n0 = n ; 1, 0 n0 MAX .
4
Temos n < MAX e 0 n MAX .
Como n0 = n + 1, 0 n0 MAX .
Buer: invari^ancia de P jbufferj MAX
jbufferj = 0 inicialmente;
113
Comando Prova
1 e 3
buffer0 = buffer, e a tese de induc~ao
(P (q0 )) se verica trivialmente;
2
Temos jbufferj MAX . Como
jbuffer0j = jbufferj ; 1, jbuffer0j MAX .
4
Temos jbufferj MAX e n < MAX .
Mas jbuffer0j = jbufferj +1, e portanto poderemos ter jbuffer0j > MAX !
E agora?
Invariantes indutivos e n~ao indutivos
Nos sabemos que jbufferj MAX e invariante; porque n~ao foi possvel
provar isto?
E que jbufferj MAX e invariante, mas n~ao e indutivo , ou seja,
e fraco como hipotese de induc~ao. Ao prolongar uma computac~ao, so
deveramos nos preocupar com computac~oes cujo ultimo estado e atingvel.
A equac~ao 6.1 considera o invariante a ser provado como indicador de
atingibilidade. Em casos como este, estamos considerando que estados
com jbufferj = MAX e n < MAX s~ao atingveis, o que nos sabemos que
n~ao e verdade.
Para provar a invari^ancia de um predicado P n~ao indutivo, prova-se a
invari^ancia de um predicado R tal que
1. R =) P , e
2. R e indutivo.
No caso, um predicado indutivo satisfatorio e
R (jbufferj = n) ^ (0 n MAX )
E importante observar a relac~ao que a prova guarda com a concepc~ao
do algoritmo: n e claramente um contador dos itens em buffer, fato
esquecido na primeira tentativa, e resgatado no predicado indutivo.
6.0.3 Variaveis Auxiliares
Vamos agora tentar provar que a sequ^encia de itens consumidos e sempre
um prexo da sequ^encia de itens produzidos.
N~ao temos como expressar esta propriedade como um predicado de estado
(uma func~ao P : Q ! ftrue; falseg);
114CAPITULO 6. MODELOS FORMAIS PARA PROGRAMAS PARALELOS
Existem duas soluc~oes para este problema:
{ enriquecer a linguagem de express~ao de propriedades do conjunto de
computac~oes de um sistema de transic~oes, ou
{ aumentar o sistema com variaveis auxiliares [Owick and Gries, 1976],
como faremos aqui;
variaveis auxiliares s~ao variaveis de estado que registram alguma historia
da execuc~ao, mas n~ao afetam o sistema, e portanto n~ao s~ao (necessariamente) implementadas;
Um subconjunto V de variaveis de estado e auxiliar se
1. variaveis em V nunca aparecem em qualquer guarda de comando, e
2. o valor de uma variavel em V nunca afeta o valor de uma variavel
fora de V
Em outras palavras, as variaveis em V :
{ so aparecem em comandos de atribuica~o, e
{ quando aparecem no lado direito do comando de atribuic~ao, a variavel
alvo tambem e auxiliar.
Buer com variaveis auxiliares
Variaveis acrescentadas:
Variavel Valores Valor Inicial
consumed char
produced char
Comandos:
Com Guarda
1
consumerState = thinking
2
consumerState = hungry ^ n > 0
3
4
|Ac~ao
|consumerState = hungry;
|consumption = buer.head();
buer = buer.tail(); n = n - 1;
consumerState = thinking; consumed.append(consumption);
producerState = thinking
|producerState = hungry; product = randomChar();
producerState = hungry ^ n < MAX |buer.append(product); n = n
+ 1; producerState = thinking;
consumed.append(product);
115
Buer: P consumed produced n~ao e indutivo
Claramente P e valido inicialmente.
Comando Prova
1 e 3
evidente, pois consumed0 = consumed
e produced0 = produced.
4
Temos consumed produced,
consumed0
=
consumed e
produced0 = produced + product.
Portanto, consumed0 produced0 .
2
Temos consumed produced,
produced0
=
produced mas
consumed0
=
consumed +
buffer:head().
Problema: P n~ao e indutivo!
Buer: R consumed + buffer = produced e indutivo
Claramente R =) P , e R e valido inicialmente;
Comando Prova
1 e 3
N~ao afetam as variaveis em R
2
n > 0, e portando buffer = a + x, onde a e um char, e x uma sequ^encia (talvez nula) de char. Sendo assim, temos
consumed0 = consumed + a, buffer0 =
x e portanto consumed0 + buffer0 =
consumed + a + x = consumed +
buffer = produced = produced0 .
4
consumed0 = consumed, buffer0 =
buffer + product, e produced0 =
produced + product.
Portanto
consumed0 + buffer0 = produced0 .
6.0.4 Atingibilidade: o mais forte invariante
Dado um predicado P proposto como invariante de um sistema de transic~oes, podemos
1. Contestar a invari^ancia, exibindo uma computac~ao em que P e violado. Por exemplo, a invari^ancia de P n = 0 e contestada por
qualquer computac~ao em que um item chegue a ser produzido.
116CAPITULO 6. MODELOS FORMAIS PARA PROGRAMAS PARALELOS
2. Provar a invari^ancia, encontrando um predicado indutivo R mais
forte que P .
Esta segunda etapa n~ao e facil, devido aos seguintes resultados[Keller, 1976]:
{ Seja A o predicado que e valido para todos os estados atingveis de
um sistema de transic~oes T ;
{ Claramente A e indutivo, e e o mais forte invariante de T (qualquer
predicado mais forte que A n~ao e invariante)
{ Portanto, se P for um invariante, existe sempre um predicado indutivo R mais forte que P , que pode ser usado na prova
{ Mas como encontrar este invariante indutivo? Isto n~ao e decidvel,
pois seria equivalente a resolver o problema da parada da maquina
de Turing.
Existem heursticas para se encontrar um invariante indutivo, mas na
pratica, uma boa compreens~ao do algoritmo e essencial.
6.1 Modelos Formais: Progresso
Propriedades de progresso t^em a forma
P leads;to Q
Esta propriedade e satisfeita por um sistema de transic~oes se em toda
computac~ao, toda vez que o estado satisfaz P , mais tarde (ou naquele
momento) na computac~ao o sistema satisfara Q.
Exemplos:
{ q = q0 leads;to q = qf inal: toda computac~ao termina
{ q = hungry leads;to q = eating: toda requisic~ao e satisfeita
{ jproducedj = n leads;to jconsumedj = n: a sequ^encia produzida
acaba sendo consumida
Problema: quanto tempo temos que esperar? Em outras palavras, quando
podemos acusar uma computaca~o de violar uma propriedade P leads;to Q?
{ num sistema assncrono, nada obriga um comando com a guarda
habilitada a ser executado;
{ a exist^encia de computac~oes nitas, em que uma requisic~ao foi foi
feita mas n~ao foi satisfeita, n~ao deveria nos levar a diagnosticar o
sistema de transic~oes como sujeito a starvation.
6.1. MODELOS FORMAIS: PROGRESSO
117
Equidade fraca e equidade forte
Os problemas para a caracterizac~ao de propriedades de progresso podem
ser contornados
{ tornando todas as computaco~es innitas , atraves da obrigato-
riedade da exist^encia de um comando guardado skip = (true; identity)
em todos os sistemas de transic~oes.
{ skip sempre pode ser escolhido para prolongar uma computac~ao nita, pois sua guarda sempre esta habilitada
{ a ac~ao de skip n~ao altera o estado, pois e a func~ao identidade
{ desta forma a toda computac~ao nita corresponde uma computac~ao
innita, que e o seu prolongamento por innitos skip .
o progresso e forcado, excluindo computac~oes innitas que n~ao satisfazem
hipoteses de equidade sobre certos comandos guardados:
Equidade fraca : para certos comandos, computac~oes em que o comando
permanece com sua guarda continuamente habilitada sem ser executado
s~ao excludas
{ Exemplo: a hipotese de equidade fraca relativa ao comando 1 = (g =
consumerState = thinking, a = consumerState = thinking) signica
que n~ao se admitem computac~oes em que o processo consumidor se
esqueca eternamente de tentar consumir
Equidade forte : para certos comandos, computac~oes em que o comando
nunca e executado, apesar de ter a sua guarda habilitada e desabilitada
intermitentemente, por um numero innito de vezes, s~ao excludas
Exemplo: Inteiro Oscilante
Exemplo: considere o sistema abaixo, cujo estado e denido por uma unica
variavel i, com valor inicial i = 0
Com Guarda Ac~ao
1
i=0
i := ;1
2
i = ;1 i = 0
3
i=0
i=1
4
i=1
i=0
{ Se este sistema obedece a hipotese de equidade fraca sobre 1, 2
e 3 , ent~ao ele admite computac~oes (innitas) em que 3 nunca e
executado;
{ se 1 e 2 s~ao executados com equidade fraca, mas 3 e executado
com equidade forte, ent~ao o sistema n~ao admite computac~oes em que
3 nunca e executado.
118CAPITULO 6. MODELOS FORMAIS PARA PROGRAMAS PARALELOS
Sistemas de Transic~oes de Estados: alterac~oes para prova
de propriedades de progresso
inclus~ao obrigatoria de skip em todo sistema
toda computac~ao e innita
hipoteses de equidade fraca ou forte excluem as computac~oes innitas que
n~ao as obedecem.
6.1.1 Tecnicas de Prova de P leads;to Q
Basicamente temos dois tipos de regras de prova:
{ regras do tipo leads;to via um comando guardado , e
{ Regras de fechamento (closure rules ) que nos permitem inferir
asserco~es leads;to de outras asserc~oes leads;to , como
P leads;to R ^ R leads;to Q =) P leads;to Q
Prova de P leads;to Q via com equidade fraca
E preciso estabelecer os seguintes pontos:
por hipotese, e executado com equidade fraca;
P =) g, onde g e a guarda de { ( sempre esta habilitado enquanto P for valido)
a execuc~ao de leva a validac~ao de Q
a execuc~ao de qualquer outro comando =2 ;; =
6 , que esteja habilitado quando P for valido acarreta a validaca~o de P _ Q
{ ( ou bem provoca a ocorr^encia de Q, ou mantem habilitado)
Com o estabelecimento destes pontos, uma computaca~o innita que viole P leads;to Q
esta descartada:
suponha a exist^encia de uma computac~ao em que P foi valido num instante
i, e Q n~ao se verica para nenhum instante j maior ou igual a i;
esta computac~ao teria a guarda de habilitada em todo instante j i, o
que contradiz a hipotese de equidade fraca para 6.1. MODELOS FORMAIS: PROGRESSO
119
Prova de P leads;to Q via com equidade forte
Os seguintes pontos devem ser estabelecidos:
por hipotese, e executado com equidade forte;
P =) g, onde g e a guarda de { ( sempre esta habilitado enquanto P for valido)
a execuc~ao de leva a validac~ao de Q
a execuc~ao de qualquer outro comando =2 ;; =
6 , que esteja habili-
tado quando P for valido acarreta a validade de um predicado R tal que
R leads;to (P _ Q)
{ (a execuc~ao de leva ou bem a validac~ao futura de Q, ou bem a
re-habilitac~ao de ).
Com o estabelecimento destes pontos, uma computac~ao innita que viole P leads;to Q
esta descartada:
suponha a exist^encia de uma computac~ao em que P foi valido num instante
i, e Q n~ao se verica para nenhum instante j maior ou igual a i;
esta computac~ao teria a guarda de habilitada por um numero ilimitado de vezes apos o instante i, mas nunca teria sido executado, o que
contradiz a hipotese de equidade forte.
Equidade forte e fraca: Exemplo
Equidade x = 0 leads;to x = 1 x = 1 leads;to x = 0 x = 0 leads;to x = ;1 x = ;1 leads;to x = 0
{
F
F
F
F
Fraca
F
T
F
T
Forte
T
T
T
T
6.1.2 Produtor e Consumidor
Voltando ao buer limitado: Prova de
jproducedj l leads;to jconsumedj l
(6.2)
para qualquer inteiro positivo l.
Para isto basta provar que
jproducedj l ^ jconsumedj = k < l leads;to jconsumedj = k + 1
(6.3)
120CAPITULO 6. MODELOS FORMAIS PARA PROGRAMAS PARALELOS
Vemos aqui um exemplo de uma regra de fechamento interessante, com o uso
de uma metrica :
temos l ; jconsumedj como uma metrica
se a metrica for igual a 0, teremos atingido o progresso desejado;
se a metrica for maior que 0, nos provamos que ela sempre diminui;
uma metrica (obviamente) n~ao possui uma sequ^encia innita decrescente
e maior que zero
Portanto, para provar 6.2, e suciente a prova de 6.3.
Buer Limitado: Progresso
Vamos precisar de ter como hipotese a execuc~ao de 1 e de 2 com equidade
fraca.
Seja
P jproducedj l ^ jconsumedj = k < l
Temos
P = P ^ (consumerState = hungry _ consumerState = thinking)
Mas
consumerState = thinking leads;to consumerState = hungry
via 1 . Como jproducedj = jbufferj + jconsumedj P implica em n = jbufferj >
0, e portanto P leads;to jconsumedj = k +1 (via 2 ), como queramos demonstrar.
Modelos Formais: Conclus~oes
Modelos formais nos permitem discursar com precis~ao sobre as propriedades de um programa paralelo
A prova de uma propriedade nos leva a um conhecimento detalhado de
um algoritmo
Modelos formais devem ser usados com sensatez: propriedades obvias devem ser formuladas e tomadas como verdadeiras, e propriedades n~ao obvias
merecem o esforco da prova.
Ter em mente o conjunto de propriedades expressas formalmente ao criar
um algoritmo e uma enorme vantagem, como veremos mais tarde.
Cap
tulo 7
Transaco~es e o Protocolo
2-fases
Fonte: The Notions of Consistency and Predicate Locks in a Database
System
K. P. Eswaran, J. N. Gray, R. A. Lorie, I. L. Traiger, CACM, 1976
Aspectos importantssimos de sistemas de transac~oes, como deadlocks,
recuperac~ao de transac~oes e toler^ancia a falhas n~ao s~ao examinados aqui .
Um tratamento formal mais completo encontra-se nos captulos 2 e 3 do livro
\Concurrency Control and Recovery in Database Systems"[Bernstein et al., 1987]
Para saber tudo sobre sistemas de transac~oes a refer^encia pratica e teorica e o livro \Transaction Processing: Concepts and Techniques"[Gray and Reuter, 1993b]
Introduc~ao
Banco de Dados: conjunto de entidades
Consist^encia expressa por um conjunto de invariantes :
A e um contador para B
C e um contador para as celulas livres em D
E e um ndice para F
Estes invariantes s~ao chamados de restrico~es de consist^encia do banco de
dados
Um estado do BD e consistente se satisfaz as restric~oes de consist^encia
121
~ E O PROTOCOLO 2-FASES
CAPITULO 7. TRANSACOES
122
Transac~oes
Ac~oes modicam o estado
Sobre cada entidade, locks e unlocks podem ser usados para evitar conitos
Pode ser necessario violar temporariamente a consist^encia do sistema
Transac~oes s~ao agrupamentos de aco~es em unidades de consist^encia :
Cada transac~ao, quando executada isoladamente, transforma um estado consistente em outro estado consistente
E este o acordo entre o controle de concorr^encia do banco de dados e o programador de transac~oes, que
pode pensar que esta sozinho no sistema
tem que garantir a consist^encia da sua transaca~o em condic~oes de isolamento
maximizar o paralelismo, dando a cada transac~ao uma
vis~ao consistente do sistema
Problema:
Escalonamentos
Um escalonamento e uma sequ^encia de aco~es de um conjunto de transac~oes
Mais uma vez: consist^encia 6= determinismo
7.0.1 Travamentos
Consideremos as transac~oes:
T1
A := A + 100;
B := B + 100;
T2
A := 2*A;
B := 2*B;
e suponhamos que a unica restrica~o de consist^encia seja A = B.
T1 e T2 s~ao individualmente consistentes, mas sua execuc~ao simult^anea pode
provocar os seguintes efeitos:
Inconsist^encia temporaria : entre o primeiro e o segundo comando de
cada transac~ao, A=B n~ao e obedecida
Conitos em uma das entidades
123
Conitos resultantes de um escalonamento em que apos o termino
das transac~oes o estado do sistema resulte inconsistente
A inconsist^encia temporaria e inerente ao sistema, e n~ao provoca inconvenientes
Conitos t^em que ser evitados, pois levam a estados inconsistentes
Formas de se evitar conitos:
exclus~ao mutua global : penalidade inaceitavel no desempenho
particionamento em blocos com exclus~ao mutua, com cada transac~ao
restrita a um bloco: complica o acordo com o programador de transac~oes,
e e inaceitavel em muitos casos
soluc~ao adotada: travamento de entidades individuais com controle de concorr^encia forcando a consist^encia dos escalonamentos
Travamento em duas fases
O principal resultado deste artigo, e um dos mais importantes resultados do
paralelismo assncrono e o 2-phase locking protocol :
Se todas as transac~oes s~ao divididas em uma primeira fase de locks, e
em outra exclusivamente de unlocks, ent~ao todos os escalonamentos
s~ao consistentes
Transac~oes: Denic~ao Formal
Uma transac~ao T e uma sequ^encia
[(T; a1; e1 ); : : : ; (T; an ; en)]
onde
ai e uma ac~ao
ei e uma entidade
Ac~oes s~ao sempre
operac~oes de escrita, ou
locks, ou
unlocks
Ac~oes de leitura s~ao omitidas para simplicar
124
~ E O PROTOCOLO 2-FASES
CAPITULO 7. TRANSACOES
Transac~oes bem formadas
Uma transac~ao e bem formada se
em uma transac~ao, uma entidade e so e travada se estiver destravada e
vice-versa
ao terminar, uma transac~ao tera destravado todas as entidades que travou
toda ac~ao sobre uma entidade e se faz com e travada, a n~ao ser que seja
um lock
Exemplo de transac~oes bem formadas:
T1
lock A
A := A + 100;
unlock A
lock B
B := B + 100
unlock B
T2
lock A
A := A*2
lock B
unlock A
B := B * 2
unlock B
Escalonamentos
Um escalonamento S e uma sequ^encia obtida intercalando-se as ac~oes de
T1 ; : : : ; Tn
Um escalonamento e legal se nenhuma transac~ao trava uma entidade ja
travada por outra
Um escalonamento serial n~ao intercala ac~oes de transac~oes distintas: S =
Ti1 ; Ti2 ; : : : ; Tin
Um escalonamento S induz uma relac~ao de depend^encia entre transac~oes
que usem uma mesma entidade e:
(T1 ; e; T2) 2 DEP (S )
se e somente se
S = [: : : ; (T1 ; a1 ; e); : : : ; (T2 ; a2 ; e); : : :]
e se n~ao existe nenhuma ac~ao (Tj ; aj ; e) escalonada no intervalo (T1 ; a1 ; e); : : : ; (T2 ; a2 ; e).
( a sada de T1 e a entrada de T2 ; por este motivo a relac~ao DEP e
chamada por alguns autores de reads-from ).
Observac~ao: se T1 e T2 s~ao bem formadas,
a1 deve ser unlock e, e
a2 deve ser lock e
125
Aciclicidade da relac~ao de depend^encia
Para os escalonamentos seriais, a relac~ao de depend^encia deve ser acclica:
(T1 ; e1 ; T2 ) 2 DEP =)6 9e2 ; (T2 ; e2 ; T1 ) 2 DEP
Os escalonamentos S1 e S2 s~ao equivalentes se
DEP (S1 ) = DEP (S2 )
Porque?
mesmo estado inicial
mesma vis~ao do banco de dados para cada uma das transac~oes
Um escalonamento S e consistente se for equivalente a algum escalonamento
serial
Exemplos de escalonamentos
S1
A := A + 100
A := 2*A
B := B + 100
B := 2*B
DEP (S1 )
( T1 , A, T2 )
( T1 , B, T2 )
S2
A := A + 100
A := 2*A
B := 2*B
B := B + 100
DEP (S2 )
( T1 , A, T2 )
( T2 , B, T1 )
S3
A := A + 100
B := B + 100
A := 2*A
B := 2*B
DEP (S3 )
( T1 , A, T2 )
( T1 , B, T2 )
Transac~oes duas-fases
Na primeira fase ( expans~ao ) s~ao permitidos locks
Na segunda fase ( contrac~ao ), que se inicia com o primeiro unlock, n~ao s~ao
permitidos locks.
Se um sistema possui uma transac~ao que n~ao e duas-fases, e possvel acrescentar a este sistema uma transac~ao duas-fases que permite a construc~ao de um
escalonamento legal e inconsistente.
O escalonamento S abaixo e legal e inconsistente:
126
~ E O PROTOCOLO 2-FASES
CAPITULO 7. TRANSACOES
unlock e1
lock e1
write e1
lock e2
write e2
unlock e1
unlock e2
lock e2
pois tanto (T1 ; e1 ; T2 ) inDEP (S ) como T2 ; e2 ; T1) 2 DEP (S )
Teorema das transac~oes duas-fases
Se toda transac~ao em um sistema e bem formada e duas-fases, ent~ao
qualquer escalonamento legal S e consistente
Prova em duas partes:
1. mostrar que a relac~ao de depend^encia e sempre acclica
2. construir um escalonamento serial equivalente
Aciclicidade da relac~ao de depend^encia
Consideremos a relac~ao denida por
Ti Tj se e somente se 9e; (Ti ; e; Tj ) 2 DEP (S )
onde S e um escalonamento legal qualquer. Vamos provar que e acclica.
O escalonamento S dene tambem para cada transac~ao Ti o inteiro shrink(Ti ),
que e a posic~ao em S do primeiro unlock de Ti .
Proposic~ao: T1 T2 =) shrink(T1 ) < shrink(T2 )
Prova: se (T1 ; e; T2) 2 DEP (S ), ent~ao
S = [: : : ; (T1 ; a1 ; e); : : : ; (T2 ; a2 ; e); : : :]
e se n~ao existe nenhuma ac~ao (Tj ; aj ; e) escalonada no intervalo (T1 ; a1 ; e); : : : ; (T2 ; a2 ; e).
Portanto, a1 e unlock e, e a2 e lock e, e shrink(T1 ) < shrink(T2 ).
De onde e uma relac~ao acclica.
Escalonamento Serial Equivalente
A func~ao shrink ordena totalmente as transac~oes de um sistema duas-fases
Esta ordenac~ao e usada para construc~ao do escalonamento serial equivalente.
Qualquer outra ordem total compatvel com tambem serviria
~
7.1. CONCLUSOES
127
7.1 Conclus~oes
Se as transac~oes T1 ; : : : ; Tn s~ao bem formadas e duas-fases, ent~ao qualquer
escalonamento legal e consistente
Se uma transac~ao T n~ao e bem-formada ou duas-fases, existe uma transac~ao T 0 e um escalonamento legal de T e T 0 que n~ao e consistente
Existem sistemas de transac~oes que n~ao s~ao duas-fases e que so possuem
escalonamentos consistentes:
T1
lock A
A := A + 100;
unlock A
lock B
B := B + 100
unlock B
T2
lock A
A := 2 * A
unlock A
lock C
C := C * 2
unlock C
Modelos formais servem para o estudo e prova de resultados
gerais da mais alta import^ancia pratica
128
~ E O PROTOCOLO 2-FASES
CAPITULO 7. TRANSACOES
Parte III
Programac~ao Distribuda
129
Cap
tulo 8
Programac~ao Distribuda
Sistemas separados sicamente, com diculdades de comunicac~ao
Diversos modelos de programac~ao, dependendo do nvel em que se trabalha
Modelo basico: troca de mensagens (message passing systems )
{ N~ao existe memoria compartilhada
{ N~ao existe relogio comum
{ A interac~ao se faz exclusivamente por trocas de mensagens, que t^em
tempos de transmiss~ao arbitrariamente longos
{ Perdas de mensagens e invers~oes na ordem de entrega algumas vezes
devem ser consideradas.
Outros modelos: chamada remota de procedimentos, objetos distribudos,
etc.
Sistemas com Trocas de Mensagens
Principal problema: cada stio deve tomar decis~oes baseado em dados
locais;
O estado dos dados locais e uma func~ao dos dados iniciais e das mensagens
recebidas
Uma mensagem traz informac~ao do passado, e cabe ao programador forcar
comportamentos que impliquem na validade da informac~ao trazida pela
mensagem.
A aus^encia de memoria comum probe comandos em que a guarda ou a
ac~ao envolva variaveis de dois ou mais stios
131
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
132
A aus^encia de relogio comum impede a programac~ao de mudancas sincronizadas.
Enfoque: compartilhamento de recursos. Porque?
enunciado simples
diversidade de soluc~oes
propriedades exigidas incluem invari^ancia e progresso
e principalmente gosto pessoal do professor. . .
8.1 The Drinking Philosophers Problem
Fonte: \The Drinking Philosophers Problem", Chandy e Misra, 1984[Chandy and Misra, 1984]
Introduc~ao
Problema: resoluc~ao equ^anime de conitos em sistemas distribudos[Chandy and Misra, 1984]
Conitos podem ser resolvidos por uma propriedade que:
{ sempre consiga decidir o vencedor de um conito ( distinguibilidade )
{ nunca deixe alguem morrer de fome ( equidade )
Soluc~oes conhecidas: prioridades (tickets) e selec~ao probabilstica (veremos mais tarde).
Proposta: uso da localizac~ao de recursos virtuais como propriedade de
resoluc~ao
O Problema dos Filosofos Sedentos : paradigma para resoluc~ao de
conitos em sistemas distribudos
Generalizac~ao do Jantar dos Filosofos proposto por Dijkstra
Grafos de Conitos e de Preced^encias
Grafo de conitos G:
{ nos: processos
{ n~ao dirigido
{ aresta (u; v) existe se for possvel um conito entre u e v
8.1. THE DRINKING PHILOSOPHERS PROBLEM
133
Grafo de preced^encias H :
{ e denido por uma func~ao que sempre atribua preced^encias distintas
a pares de processos em conito
{ id^entico a G, mas dirigido
{ u ! v em H se u tem preced^encia sobre v
Exemplos de Grafos de Conito e de Preced^encias
1
3
2
4
6
5
Grafo de Conflitos
1
1
3
2
3
2
4
4
6
5
Grafo de Precedencias Aciclico
6
5
Grafo de Precedencias com Ciclo
Profundidade de u em um grafo acclico: maior numero de arestas em uma
rota que sai de um no sem precedentes e vai ate u
Se H for acclico, a profundidade sempre vai diferenciar de todos os concorrentes
potenciais ( vizinhos em G) Porque?
Se H for cclico, nem todos os conitos poder~ao ser resolvidos
Modicando o Grafo de Preced^encias
H so pode ser modicado por mudancas nas direc~oes das arestas
Proposta: implementac~ao distribuda de H que garanta que
1. H permanece acclico
2. H seja modicado de maneira a garantir que todo processo em conito chegue a profundidade 0 num tempo nito
3. toda mudanca em H possa ser feita localmente
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
134
Regra da Aciclicidade
1
1
3
2
3
2
4
4
6
5
6
1
5
1
3
2
3
2
4
6
4
5
6
5
Regra da Aciclicidade :
se um grafo de preced^encias e acclico, ele permanece acclico se todas
as arestas incidentes em um no s~ao dirigidas a ^ele numa ac~ao at^omica
Prova: suponha que o grafo resultante de uma operac~ao como esta sobre o no i
contenha um ciclo.
Se este ciclo n~ao contem i, ele ja existia, o que contraria a nossa hipotese
Se este ciclo contem i estamos tambem diante de uma impossibilidade,
pois todas as arestas incidentes em i est~ao dirigidas a ele.
Regra da Equidade
Regra da Equidade : Todo processo vencedor de um conito deve dar preced^encia a todos os seus vizinhos dentro de um tempo nito apos a vitoria
Problema: implementac~ao distribuda de H : decis~oes devem ser tomadas
com base em dados locais
8.1. THE DRINKING PHILOSOPHERS PROBLEM
135
O Problema dos Filosofos Sedentos
Cada losofo (processo) esta em um vertice de um grafo G n~ao dirigido
Pode estar em um de tr^es estados:
1. tranquilo
2. sedento
3. bebendo
A cada aresta de G esta associada uma garrafa disputada por dois losofos
Um losofo so bebe de garrafas associadas a arestas incidentes
Um losofo tranquilo pode ser acometido de sede por um coquetel (conjunto de
garrafas) especco
Um losofo pode desejar diferentes coqueteis para cada drinque
De posse das garrafas que comp~oem o coquetel desejado, o losofo pode comecar
a beber
Apos um tempo nito bebendo, o losofo volta a car tranquilo
Um losofo permanece tranquilo por um tempo arbitrario
1
Anis
3
2
Martini
4
Whiskey
Campari
Caipira
6
5
Grafo de Conflitos
Condic~oes para uma soluc~ao
Equidade :
nenhum losofo morre de sede
Simetria :
mesmos direitos e deveres
Concorr^encia : drinques simult^aneos de garrafas distintas n~ao devem
ser proibidos
Economia :
um losofo troca um numero nito de mensagens para uma transic~ao de estado
Limites :
o numero e o tamanho das mensagens em tr^ansito e
limitado
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
136
O Problema dos Filosofos Famintos
Caso especial em que o coquetel desejado e sempre composto por todas
as garrafas acessveis
Estados de um losofo: pensando, faminto, comendo
Garrafas passam a ser chamadas de garfos
Dois vizinhos nunca comem simultaneamente
1
3
2
4
6
5
Grafo de Conflitos
Se o grafo de conitos for completo, temos a exclus~ao mutua global
Soluc~ao \higi^enica": ideia basica
Soluc~ao \higi^enica":
{ um garfo esta sujo ou limpo
{ garfos (so) sujam-se ao serem usados para comer
{ garfos (so) s~ao limpos ao serem enviados
{ um losofo comendo so responde a requisic~oes ao acabar de comer
{ um losofo faminto:
atende a requisic~oes por garfos sujos
adia respostas a requisic~oes por garfos limpos
Base da soluc~ao: representac~ao distribuda do grafo H
u precede v em H (u ! v) sse
1. u possui fuv , o garfo compartilhado com v, limpo, ou
2. v possui fuv , sujo, ou
8.1. THE DRINKING PHILOSOPHERS PROBLEM
137
3. fuv esta em tr^ansito indo de v para u,
A situac~ao inicial deve garantir que o grafo formado por estas regras e
acclico
A Soluc~ao Higi^enica: Preliminares
Entre u e v circula tambem um request token
So o possuidor de um token pode envia-lo
Se um processo possui o garfo e o token que compartilha com um vizinho,
e porque existe uma requisic~ao pendente deste vizinho
forku (f )
u detem o garfo f
reqf
(
f
)
u detem o token associado ao garfo f
Variaveis: dirtyuu (f )
u detem f , sujo
thinkingu=hungryu=eatingu u esta thinking=hungry=eating
A Soluc~ao Higi^enica: Comandos Guardados
R1 Requisitando um garfo f :
hungry, reqf (f ), :fork(f ) !
send request token for fork f ;
reqf (f ) := false
R2 Entregando um garfo f :
:eating, reqf (f ), dirty(f ) !
send fork f ;
dirty(f ) := false;
fork(f ) := false
R3 Recebendo um request token por f :
receive(ReqToken(f )) !
reqf (f ) := true
R4 Recebendo um garfo f :
receive(fork(f )) !
fork(f ) := true
R5 Comecando a comer :
hungry, all forks !
hungry := false;
eating := true;
dirty(f ) := true for all f
R6 Acabando de comer :
eating !
eating := false; thinking := true;
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
138
Observac~oes
R1 corresponde a n comandos guardados, sendo um para cada processo
(losofo)
Os ndices dos processos s~ao omitidos para simplicar a notac~ao
A Soluc~ao Higi^enica: Condic~oes Iniciais
1. Todos os garfos est~ao sujos :
8f; dirtyu(f ) _ dirtyv (f )
2. Todo garfo f e o request token associado est~ao com vizinhos distintos
forku (f ); reqfv (f ); :forkv (f ); :reqfu (f )
_
forkv (f ); reqfu (f ); :forku (f ); :reqfv (f )
3. Os garfos est~ao dispostos de maneira a fazer H acclico
Filosofos Sedentos: o Grafo de Preced^encias
A soluc~ao higi^enica e uma implementaca~o distribuda do grafo de preced^encias
Olhando-se apenas o estado de um losofo u, so e possvel determinar a
relac~ao de preced^encia entre u e um vizinho v se u detem fuv
Garfos s~ao utilizados como artefatos para implementac~ao de H
Estado de um losofo: par (estado faminto, estado sedento)
Transic~oes de um losofo faminto:
D1 Um losofo com sede e pensando ca com fome
D2 Um losofo comendo mas sem sede passa a pensar
Regra para resoluc~ao de conitos:
D3 O losofo u envia uma garrafa em resposta a uma requisic~ao de v sse
{ u n~ao precisa da garrafa, ou
{ u n~ao esta bebendo e n~ao detem fuv
A notar que a decis~ao do envio da garrafa e baseada na percepc~ao local de
preced^encia
~ MUTUA
8.2. EXCLUSAO
DISTRIBUIDA
139
Algoritmo para Filosofos Sedentos
R1 Requisitando uma garrafa :
thirsty, need(b), reqb(b), :bot(b) !
send request token for bottle b;
reqb(b) := false
R2 Enviando uma garrafa :
reqb(b), bot(b), :[need(b) ^ (drinking _ fork(f ))] !
send bottle b;
bot(b) := false
R3 Recebendo uma requisic~ao por garrafa :
receive(request(b)) !
reqb(b) := true
R4 Recebendo uma garrafa :
receive(bottle(b)) !
bot(b) := true
Conclus~ao
Um problema de sincronizac~ao complexo, com a diculdade adicional dos
ambientes distribudos, foi resolvido porque: estrutura de prova de correc~ao foi concebida junto com o algoritmo
8.2 Exclus~ao Mutua Distribuda
Ambiente
{ diversos stios com memoria e processamento local;
{ comunicac~ao exclusivamente por trocas de mensagens
{ sem memoria e sem relogio comuns;
Problema
{ atingir a exclus~ao mutua
Restric~oes
{ aus^encia de bloqueios
{ aus^encia de inanic~ao
{ simetria: mesmos direitos, mesmos deveres
Porque exclus~ao mutua?
{ Enunciado simples
140
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
{ Diversas soluco~es exemplicando tecnicas de programac~ao
{ Alguma utilizaca~o pratica (pouca)
8.2.1 Relogios Logicos e Timestamps
Relogios logicos [Lamport, 1978] s~ao inteiros monotonamente crescen
tes conservados pelos stios;
usados para etiquetar mensagens e para estabelecer prioridades
;
o valor da etiqueta de uma mensagem { seu timestamp { e o valor
corrente do relogio logico no momento do envio;
a prioridade de uma requisic~ao e o valor corrente do relogio logico
no momento da operac~ao;
empates s~ao costumeiramente resolvidos pelo numero unico do stio;
podem ser incrementados a qualquer momento;
devem ser atualizados para permanecerem maiores que a etiqueta
de qualquer mensagem recebida ;
devem ser incrementados entre certos eventos;
Algoritmo de Lamport (1978)
o meio de comunicac~ao conserva a ordem de envio na entrega das
mensagens;
cada stio possui uma la de requisic~oes ;
inicialmente o stio 0 possui o recurso crtico;
todas as las de requisic~oes possuem a mensagem < T;1 : 0; request >
onde T;1 e menor que o valor inicial de qualquer relogio logico;
O algoritmo e denido pelas seguintes regras:
1. Requisic~ao : o stio i manda a mensagem < Ti : i; request > para
todos os outros stios, e tambem coloca esta mensagem em sua la
de requisic~oes;
2. Recepc~ao de < Tj : j; request > : a requisica~o e colocada na la,
e uma mensagem < Ti : i; ack > e enviada ao stio j ;
3. Liberac~ao : o stio i remove toda mensagem < Ti : i; request >
de sua propria la de requisic~oes, e manda < Ti : i; release > para
todos os outros stios;
~ MUTUA
8.2. EXCLUSAO
DISTRIBUIDA
141
4. Recepc~ao de < Tj : j; release > : o stio i remove toda mensagem
< Tj : j; request > de sua la de requisic~oes;
5. Incio de sec~ao crtica : o stio i pode comecar a utilizar o recurso
quando:
(a) a requisic~ao mais prioritaria em sua la e da forma < Ti :
i; request >, e
(b) o stio i ja recebeu mensagens com prioridade menor que (Ti ; i)
de todos os outros stios;
Algoritmo de Lamport - Seguranca
\Prova" de exclus~ao mutua:
suponha a exist^encia de uma computac~ao em que dois stios i e j est~ao
em suas sec~oes crticas simult^aneamente;
sem perda de generalidade, suponhamos que (Ti : i) tenha prioridade sobre
(Tj : j );
na operac~ao de requisic~ao, i enviou < Ti : i; request > para j ;
no momento da entrada de j em sua sec~ao crtica,
{ se j n~ao tinha recebido este request, para entrar em sua sec~ao crtica
j teria recebido outra mensagem de i, com prioridade menor que
(Tj : j ), o que e impossvel pois o meio de transmiss~ao conserva a
ordem de envio, e as mensagens enviadas por i recebem timestamps
crescentes;
{ se j ja tinha recebido este request, para entrar em sua sec~ao crtica
j teria que t^e-lo eliminado de sua la, o que so aconteceria com a
chegada do < release > correspondente, o que contradiz a hipotese
de simultaneidade das sec~oes crticas;
portanto esta computaca~o n~ao pode existir
Algoritmo de Lamport - Progresso
Suponhamos a exist^encia de uma computac~ao innita em que o stio i
requisitou a sec~ao crtica num instante Ti , e nunca conseguiu.
Se i n~ao conseguiu, e porque existe um stio j que nesta computac~ao:
{ enviou um < Tj : j; request > para i, com prioridade superior a
< Ti : i; request >, e que nunca saiu da la de i,
{ isto nao aconteceu, mas j nunca enviou uma mensagem para i com
prioridade inferior a < Ti : i; request >
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
142
No segundo caso, j teria recebido o < Ti : i; request >, e n~ao teria enviado
para i o < Tj : j; ack > correspondente, o que n~ao pode acontecer;
No primeiro caso, j n~ao enviou < Tj0 : j; release >, e como todo stio
entrega o recurso crtico apos um tempo nito, o unico motivo para j ter
morrido de fome e a exist^encia de j 0 , mais prioritario que j , que tambem
morreu de fome, por culpa de j 00 , mais prioritario que j 0 , e assim por
diante.
Como n~ao existe uma sequ^encia innita como esta, a computac~ao com inanic~ao
n~ao pode existir, c.q.d.
Exemplo
0
0
1
1
0
1
1
1
1
2
2
2
2
2
2
3
3
3
4
4
4
~ MUTUA
8.2. EXCLUSAO
DISTRIBUIDA
143
Algoritmo de Lamport: Complexidade
Em cada sec~ao crtica, temos:
n ; 1 requests
n ; 1 acks
n ; 1 releases
com um total de 3(n ; 1) mensagens por sec~ao crtica
8.2.2 Algoritmo de Ricart e Agrawala (1981)
Evoluc~ao do algoritmo de Lamport, em que releases so s~ao enviados quando o
no requisitante tem prioridade
Fonte: \An optimal algorithm for mutual exclusion in computer networks"[Ricart and Agrawala, 1981].
CONST i = /* this node unique number */
VAR OSN, /* Our Sequence Number */
HSN, /* Highest Sequence Number */
ORC /* Outstanding Reply Count */
: CARDINAL;
Hungry: BOOLEAN;
Deferred: ARRAY[1..n] OF BOOLEAN;
PROCEDURE Request();
BEGIN
lock(mutex);
Hungry := TRUE; OSN := HSN + 1;
send(request(OSN, me), j) to every j <> i;
ORC := n-1;
WHILE ORC > 0 DO Sleep(B, mutex);
unlock(mutex);
END Request;
Algoritmo de Ricart e Agrawala - 2
PROCEDURE Release();
BEGIN
lock(mutex);
Hungry := FALSE;
FOR j := 1 TO n DO
IF Deferred[j] THEN
144
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
send(reply, j); Deferred[j] := FALSE;
END;
END;
unlock(mutex);
END Release;
PROCEDURE ReceiveRequest(Tk, k: CARDINAL;);
BEGIN
lock(mutex);
HSN := MAX(HSN, Tk);
IF Hungry AND
((Tk > OSN) OR
(Tk = OSN) AND (k > i)) THEN
Deferred[k] := TRUE
ELSE
send(reply, k);
END;
unlock(mutex);
END ReceiveRequest;
PROCEDURE ReceiveReply();
BEGIN
lock(mutex)
ORC := ORC - 1;
IF ORC = 0 THEN WakeUp(B, mutex);
unlock(mutex);
END;
~ MUTUA
8.2. EXCLUSAO
DISTRIBUIDA
145
Exemplo
0
0
1
1
2
0
1
1
1
1
2
2
3
4
4
5
5
Ricart e Agrawala: Complexidade
Em cada sec~ao crtica:
n requests
n releases
com um total de 2(n ; 1) mensagens por sec~ao crtica
8.2.3 Carvalho e Roucairol (1983) { 1
GENIAL [Carvalho and Roucairol, 1983] evoluc~ao do algoritmo de Ricart e
Agrawala, que tira proveito da validade de uma autorizaca~o para \comer" mais
de uma vez sem enviar novas requisic~oes.
146
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
CONST i = /* this node unique number */
VAR OSN, /* Our Sequence Number */
HSN /* Highest Sequence Number */: CARDINAL;
A, Deferred: ARRAY [1..n] OF BOOLEAN;
Eating, Hungry: BOOLEAN;
PROCEDURE Request();
VAR j: CARDINAL;
BEGIN
lock(mutex);
Hungry := TRUE; OSN := HSN + 1;
FOR j := 1 TO n DO
IF (j <> i) AND (NOT A[j]) THEN
send(request(OSN, i),j);
WHILE NOT (A[j] = TRUE for all j <> i) DO Sleep(B,mutex);
Hungry := FALSE; Eating := TRUE;
unlock(mutex);
END Request;
Carvalho e Roucairol (1983) { 2
PROCEDURE Release();
VAR j: CARDINAL;
BEGIN
lock(mutex);
Eating := FALSE; Thinking := TRUE;
FOR j := 1 TO n DO
IF Deferred[j] THEN
A[j] := FALSE; Deferred[j] := FALSE;
send(release(i),j);
unlock(mutex);
END Release;
PROCEDURE ReceiveRequest(Tk, k: CARDINAL);
VAR OurPriority: BOOLEAN;
BEGIN
lock(mutex);
HSN := MAX(HSN, Tk);
OurPriority := (Tk > OSN) OR
((Tk = OSN) AND (k > i));
IF Eating OR (Hungry AND OurPriority) THEN
Deferred[j] := TRUE;
ELSE /* Eating = FALSE, Hungry => NOT OurPriority */
send(release(i),j);
~ MUTUA
8.2. EXCLUSAO
DISTRIBUIDA
147
IF Hungry AND A[j] THEN send(request(OSN,i),j);
A[j] := FALSE;
END;
unlock(mutex);
END ReceiveRequest);
PROCEDURE ReceiveRelease(k: CARDINAL);
BEGIN
lock(mutex);
A[k] := TRUE; WakeUp(B, mutex);
unlock(mutex);
END ReceiveRelease;
Exemplo
3
4
0
0
0
4
5
1
1
2
1
1
5
6
1
6
4
1
7
2
7
2
3
4
6
7
7
7
4
7
5
5
8
9
10
Carvalho e Roucairol: Complexidade
Por sec~ao crtica:
entre 0 e n ; 1 requests
entre 0 e n ; 1 releases
com um total variando entre 0 e 2(n ; 1) mensagens por seca~o crtica.
8.2.4 O Algoritmo de Maekawa (1985)
Para n nos,
{ o algoritmo de Lamport usa 3:(n ; 1) mensagens por seca~o crtica,
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
148
{ Ricart e Agrawala usa 2:(n ; 1), e
{ Carvalho e Roucairol usa entre 0 e 2:(n ; 1) mensagens por sec~ao
crtica.
Nesta aula vamos explorar o uso de esquemas de comunicac~ao para
diminuir a ordem de complexidade na troca de mensagens.
Os dois algoritmos { Maekawa (1985) e Carvalho e Campos (1987) utilizam
um esquema de comunicaca~o denido por um grafo especial, chamado de
plano projetivo nito
Usando planos projetivos nitos, a complexidade e reduzida para O(pn),
ao custo de uma indirec~ao que penaliza a transfer^encia do recurso crtico
em um tempo de transmiss~ao de mensagens.
Princpios Basicos
O n
umero de mensagens trocadas por tomada de sec~ao crtica e da ordem
p
de (n);
Isto e obtido ao custo de um maior tempo de transfer^encia do recurso;
O algoritmo e simetrico: mesmos deveres e direitos para todos os stios;
E melhor compreendido se separarmos os papeis de arbitro e de cliente
de cada stio;
utiliza planos projetivos nitos para restringir as comunicac~oes;
conitos s~ao resolvidos por meio de relogios logicos , mas a ordem
FCFS nem sempre e observada[Maekawa, 1985].
Planos Projetivos Finitos { Denic~ao
1
2
3
4
5
6
~ MUTUA
8.2. EXCLUSAO
DISTRIBUIDA
149
Colec~oes de pontos e linhas , onde linhas s~ao conjuntos de pontos,
tais que[Lakshman and Agrawala, 1986]:
1. Dois pontos distintos pertencem sempre a uma unica linha
;
2. Duas linhas distintas possuem sempre um unico ponto comum ;
Linhas:
L1
L2
L3
L4
L5
L6
L7
=
=
=
=
=
=
=
f1; 2; 5g
f2; 4; 7g
f2; 3; 6g
f3; 4; 5g
f5; 6; 7g
f1; 4; 6g
f1; 3; 7g
Reparem que foi possvel enumerar as linhas mantendo o ponto i na linha Li
Planos Projetivos Finitos { Teoremas
1. Todo ponto pertence ao mesmo numero de linhas
2. todas as linhas possuem o mesmo numero de pontos
3. O numero de linhas a que um ponto pertence e igual ao numero
de pontos que uma linha possui ;
4. Sempre e possvel enumerar as linhas mantendo o ponto i per-
tencente a linha Li
5. Um ppf com m +1 pontos em cada linha (e m +1 linhas passando
por cada ponto) possui m2 + m + 1 pontos e m2 + m + 1 linhas; o
numero m e a ordem do ppf ;
6. Se m = pk , onde p e um numero primo e k e um inteiro positivo,
ent~ao existe um ppf de ordem m .
Observac~ao: a prova da conjectura de que planos projetivos nitos existem
somente para ordens m = pk , onde p e um numero primo e k e um inteiro
positivo, e um dos mais importantes problemas abertos em Combinatoria1
1
http://www.astro.virginia.edu/~eww6n/math/ProjectivePlane.html
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
150
Esquema de Comunicac~ao por ppfs
Pontos ! clientes
Linhas ! arbitros
Associac~ao:
Arbitros
1
2
3
4
5
6
7
1
2
3
4
5
6
7
Clientes
todo cliente pede autorizac~ao ao mesmo numero de arbitros ;
{ (Todo ponto pertence ao mesmo numero de linhas)
todo arbitro coordena a autorizac~ao para o mesmo numero de
clientes ;
{ (Todas as linhas possuem o mesmo numero de pontos)
dois clientes possuem sempre um unico arbitro comum ;
{ (Dois pontos distintos pertencem sempre a uma unica linha)
O cliente i utiliza o arbitro i, para economia de mensagens .
{ Sempre e possvel enumerar as linhas mantendo o ponto i pertencente
a linha Li
Para qualquer numero de stios n, e possvel encontrar n0 n tal que
2 + m + 1 pontos, onde m = pk para p primo e
exista um ppf com n0 = m
p
k positivo, onde m = O( n)
Algoritmo de Maekawa { Mensagens
Tipos de mensagens:
request usada pelos clientes para pedir aos seus arbitros sua autorizac~ao;
release usada pelos clientes para devolver aos arbitros a autorizac~ao;
locked usada pelos arbitros para conceder a autorizac~ao;
~ MUTUA
8.2. EXCLUSAO
DISTRIBUIDA
151
inquire usada pelos arbitros para indagar da possibilidade de obtenc~ao de
todas as autorizac~oes de um cliente;
failed usada pelos arbitros para dizer a um cliente que a autorizac~ao encontrase com outro cliente mais prioritario;
relinquish usada por um cliente para devolver a autorizac~ao a um arbitro,
apos ter recebido failed de outro arbitro.
Algoritmo de Maekawa { Cliente i
1. Requisic~ao : o cliente envia request(OSN, i) para todos os seus arbitros
j , e faz Failed[j] := Inquiring[j] := FALSE;
2. Recepc~ao de locked(Tk, k) : o cliente faz A[k]
:= TRUE
Failed[k] := FALSE;
3. Comeca a comer : se
utilizar o recurso;
A[j] = TRUE
e
para todos os arbitros, passa a
4. Recepc~ao de inquire(Tk, k) : se Failed[j] = TRUE para algum
arbitro j , o cliente envia relinquish(Ti,i) para o arbitro k;
sen~ao, faz Inquiring[k] := TRUE;
5. Recepc~ao de failed(Tk, k) : o cliente faz Failed[k] :=
relinquish(Ti, i) para todo arbitro j tal que Inquiring[j]
o envio, faz Inquiring[j] := FALSE;
TRUE, e envia
= TRUE; ap
os
6. Liberac~ao : o cliente envia release(Ti, i) para todos os seus arbitros;
Algoritmo de Maekawa { A rbitro j
1. Recepc~ao de request(Ti, i) : se Owner = NIL, o arbitro faz Owner := i,
OwnerTi := Ti, e envia locked(Tj,j) para o cliente i; sen~
ao, o arbitro coloca o pedido numa la. Neste caso, se (Ti, i) for mais prioritario que
(OwnerTi, Owner), o arbitro envia inquire(Tj,j) para o cliente Owner;
2. Recepc~ao de release(Ti,i) : se a la estiver vazia, o arbitro faz
Owner := NIL; sen~
ao, o arbitro envia locked(Tj, j) para o cliente k mais
prioritario, faz Owner := k e OwnerTi := Tk, e retira k da la;
3. Recepc~ao de relinquish(Ti,i) : a reac~ao e id^entica a da recepc~ao de
release, mas (Ti, i) e colocado na la;
152
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
8.2.5 Algoritmo de Carvalho e Campos (1991) { 1
GENIAL [de Aguiar Campos and Carvalho, 1988] fus~ao das ideias de
Maekawa e de Chandy e Misra;
O esquema de comunicac~ao e restrito por um plano projetivo
nito ;
Conitos s~ao resolvidos pela profundidade dos nos num grafo
acclico ;
O numero de mensagens
trocadas por sec~ao crtica varia entre 0 e um
p
maximo que e O( (n));
Stios agem como clientes e como arbitros;
Cada arbitro usa um permission token como autorizac~ao unica disputada por seus clientes;
Para comer um cliente precisa da permiss~ao de todos os seus arbitros;
Entre um cliente e um arbitro circula um request token, usado por ambos
para pedir a permiss~ao;
permiss~oes podem estar sujas ou limpas ;
ao comer, um cliente suja todas as suas permiss~oes ;
um cliente envia de volta a permiss~ao de um arbitro no estado em que ela
se encontra, suja ou limpa;
um arbitro so envia permiss~oes limpas;
cada arbitro mantem uma lista de prioridades que ordena totalmente
seus clientes;
esta lista so e modicada pelo arbitro na recepc~ao de uma permiss~ao suja, quando o cliente que a devolveu e movido para a
ultima posic~ao .
Carvalho e Campos: Grafo de Preced^encias
Sejam c e d dois clientes, e seja a seu arbitro comum; O cliente c tem
preced^encia sobre d se e somente se :
1. d possui a permiss~ao Pa , suja , ou
2. Pa esta em tr^ansito indo de d para a, e esta suja , ou
3. nenhuma das condico~es acima aplica-se a d ou a c, e Prioritya (c) >
Prioritya (d) .
~ MUTUA
8.2. EXCLUSAO
DISTRIBUIDA
153
Suponha que a permiss~ao de a foi dada a c, e que foi pedida por um outro cliente
d:
se Prioritya (d) > Prioritya (c), o arbitro a sabe que d tem preced^encia so-
bre c, e pede sua permiss~ao de volta usando uma mensagem StrongRequest;
se Prioritya (d) < Prioritya (c), a relac~ao de preced^encia entre c e d e
determinada pelo estado (suja ou limpa) de Pa , e esta informac~ao e local
ao cliente c.
Carvalho e Campos: mensagens e variaveis
Mensagens de um arbitro para um cliente: CleanPermission, request e
StrongRequest ;
Mensagens de um cliente para um arbitro: request, CleanPermission e
DirtyPermission .
Variaveis de um cliente c:
Permissionc(a)
Reqc(a) :
Strongreqc (a) :
Dirtyc (a) :
Thinkingc :
Hungryc :
Eatingc :
c tem a permiss~ao do arbitro a;
c tem a requisic~ao que compartilha com o arbitro a;
c recebeu um StrongRequest do arbitro a;
c possui a permiss~ao de a, que esta suja;
c esta pensando;
c esta com fome;
c esta comendo.
Variaveis de um arbitro a:
Ownera
cliente que esta com a permiss~ao de a; igual a NIL se Pa estiver com a;
Reqa (c)
a possui a requisica~o que compartilha com o cliente c;
StrongReqSenta a ja enviou um StrongRequest para o cliente que esta com sua permiss~ao.
Carvalho e Campos:
Algoritmo do Cliente { 1
R 1 Becoming hungry:
Thinking !
Hungry := TRUE
R 2 Starting to eat:
Hungry; 8a 2 S Permission(a) !
Eating := TRUE
8a 2 S; Dirty(a) := TRUE
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
154
R 3 Starting to think:
Eating !
Thinking := TRUE
R 4 Requesting a permission:
Hungry; a 2 S; Permission(a); Req(a) !
send(a; Request)
Req(a) := FALSE
R 5 Sending a dirty permission:
Eating; a 2 S; Permission(a); Req(a); Dirty(a) !
send(a; DirtyPermission)
Permission(a) := FALSE
Strongreq(a) := FALSE
Carvalho e Campos:
Algoritmo do Cliente { 2
R 6 Sending a clean permission:
a 2 S; Permission(a); Strongreq(a); Dirty(a) !
send(a; CleanPermission)
Permission(a) := FALSE
Req(a) := FALSE
Strongreq(a) := FALSE
R 7 Receiving a permission:
receive(a; CleanPermission) !
Permission(a) := TRUE
Dirty(a) := FALSE
R 8 Receiving a request:
receive(a; Request) !
Req(a) := TRUE
~ MUTUA
8.2. EXCLUSAO
DISTRIBUIDA
R 9 Receiving a strong request:
receive(a; StrongRequest) !
Permission(a) !
Req(P ) := TRUE
Strongreq(P ) := TRUE
Permission(a) ! SKIP
Carvalho e Campos:
Algoritmo do A rbitro { 1
R 10 Receiving a request:
receive(c; Request) !
Req(c) := TRUE
R 11 Receiving a dirty permission:
receive(c; DirtyPermission) !
Owner := NIL
GiveLeastPriorityTo(c)
R 12 Receiving a clean permission:
receive(c; CleanPermission) !
Owner := NIL
Req(c) := TRUE
R 13 Sending the permission:
Req(c); c = HighestPriorityRequest; Owner = NIL !
send(c; CleanPermission)
Owner := c
StrongReqSent := FALSE
Carvalho e Campos:
Algoritmo do A rbitro { 2
R 14 Asking back the permission, kindly:
9c; c 6= Owner; Owner 6= NIL;
Req(c); Req(Owner); Priority(Owner) > Priority(c) !
155
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
156
send(Owner; Request)
Req(Owner) := FALSE
R 15 Asking back the permission, rmly:
9c; c 6= Owner; Owner 6= NIL;
Req(c); StrongReqSent; Priority(Owner) < Priority(c) !
send(Owner; StrongRequest)
StrongReqSent := TRUE
Req(Owner) := FALSE
Condic~oes iniciais :
permiss~oes com os arbitros;
requisic~oes com os clientes;
listas de prioridades determinando um grafo acclico.
Carvalho e Campos: Exemplo { 1
priority
tables
arbiters
clients
'$ '$ '$
&% &% &%
'$
'$
'$
&% &% &%
1
3
1
2
2
3
1
r
HH
2
HH;H;
;
;
H
; HH ; ;
;
HH;H
;
;
r ; HH
H
r
r
Figura 8.1: Initial conguration
3
r
r
~ MUTUA
8.2. EXCLUSAO
DISTRIBUIDA
priority
tables
arbiters
clients
'$
'$
'$
&% &% &%
'$
'$
'$
&% &% &%
1
3
1
2
1 r
r
2
HHHH
HjH;;
;
;
H
; HHH
;
;
;
HH;
;
HHH
;
;
r
H
r
r
157
2
3
3
r
_
Figura 8.2: Client 3 got hungry
Carvalho e Campos: Exemplo { 2
Carvalho e Campos: Exemplo { 3
Carvalho e Campos: Exemplo { 4
8.2.6 O Algoritmo de Naimi-Trehel
Nesta sec~ao vamos apresentar o algoritmo de Naimi-Trehel[Naimi and Trehel, 1987],
redescoberto de forma independente por Guilherme Padua em 1994, ent~ao
aluno de iniciac~ao cientca.
E a vers~ao do Guilherme, com contribuic~oes do Marco Aurelio, do Kemio
e minhas que e apresentada aqui
utiliza um token com informaca~o suciente para manter uma la de
requisic~oes,
reduz a complexidade media para O(log n) mensagens, cujo tamanho entretanto e da ordem de n
um stio i com fome envia um unico request para o stio nexti , que ele
julga deter o token;
um stio j que recebe um request do stio i,
{ se estiver com fome ou comendo armazena a requisic~ao em uma la
local;
158
priority
tables
arbiters
clients
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
'$
'$
'$
&% &% &%
'$
'$
'$
&% &% &%
1
3
1
2
2
3
2
3
_
_
1r
r
r
HHHHj r
HH;;
;
; r
; HHHH
;
?
HH;;
;;
H
;
; HHH r
Figura 8.3: Client 2 got hungry
{ ao terminar de comer, j envia o token para o stio mais prioritario
em sua la local; a la e enviada junto com o token, e esvaziada em
seguida. nextj passa a apontar para o stio menos prioritario nesta
la.
{ se estiver pensando e n~ao estiver de posse do token, o request e retransmitido para o stio nextj ; nextj passa a apontar para o stio que
originou o request recebido (que pode ser diferente do stio que
enviou o request)
State Variables and Initial Values
Each site keeps the following variables in its private memory:
~ MUTUA
8.2. EXCLUSAO
DISTRIBUIDA
priority
tables
arbiters
clients
'$
'$
'$
&% &% &%
'$
'$
'$
&% &% &%
1
3
1 r
r
1
2
2
3
2
3
r
_
_
HHHH
r
HjH;; r
; ;;
H
;
; HHH
;
;
;
HH;
;
HHH
;
;
H
r
159
Figura 8.4: Client 3 was forced to render a clean permission
Variable Description
s
may be thinking, hungry or eating
HasToken boolean indicating the presence of
the token
ReqList
FIFO list of stored requests
Next
integer between 1 and N, or nil
T
R
Initial Value
s = thinking
TRUE for node 1; FALSE for all
other nodes
ReqList = EMPTY
for node 1, Next = nil; for all other
nodes, Next = 1
a record corresponding to a to- ken message, with a single eld,
T.ReqList, which is a FIFO list of
requests
a record corresponding to a re- quest message, with a single eld,
R.origin, indicating the site who
sent the message
Auxiliary Variables
The array V [1 : : : N] (for V isited) is used only for proof purposes.
V [k] is a sequence of node numbers. It contains the nodes already \visited" by a request originated at node k.
As an auxiliary variable, V [k] may be read or written by any node;
Initially V [k] = EMPTY for all k.
160
priority
tables
arbiters
clients
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
'$
'$
'$
&% &% &%
'$
'$
'$
&% &% &%
1
3
1
2
2
3
1
r
HrHHHj r
r
HH;; r
; ;;
H
;
; HHH
;
;
;
?
HH;
;
H
;
; HHH
2
3
r
_
_
_
Figura 8.5: Client 1 got hungry
Rules
s := hungry
s = eating, ReqList 6= EMPTY
!
!
!
!
Rule 5: requesting the token
s = hungry, Next 6= nil
!
Receive(R), s 6= thinking
Receive(R), s = thinking, Next = nil
!
!
send(Next, Request(Myself));
Next := nil;
V [Myself] := EMPTY;
Rule 8: forwarding a request
Receive(R), s = thinking, Next 6= nil
!
Rule 9: receiving the token
!
Rule 1: getting hungry
s = thinking
Rule 2: starting to eat
s = hungry, Hastoken
s = eating, ReqList = ;
Rule 3: stoping to eat, keeping the token
Rule 4: stoping to eat, sending the token
Rule 6: storing a request
Rule 7: releasing the token
Receive(T)
s := eating
s := thinking
s:= thinking ;
Next := last(ReqList);
T.ReqList := tail(ReqList);
send(head(ReqList), T); HasToken := FALSE;
ReqList := EMPTY;
for all k 2 T.ReqList do
V [k]:= V [k] cat Myself;
put(ReqList, R.origin)
T.ReqList := EMPTY;
send(R.origin, T);
HasToken := FALSE;
Next := R.origin
send(Next, R);
Next := R.origin;
V [R.origin] := V [R.origin] cat Myself;
Hastoken := TRUE;
ReqList := T.ReqList cat ReqList
V [Myself] := EMPTY;
~ MUTUA
8.2. EXCLUSAO
DISTRIBUIDA
priority
tables
arbiters
clients
'$
'$
'$
&% &% &%
'$
'$
'$
&% &% &%
1
3
1 r
HH
1
2
2
3
2
r
3
r
_
_
HH;;
;
;
H
; HHH
;
;
;
HH;
;
HHH
;
r r;
H
r
^
161
Figura 8.6: Client 1 eats and dirties his permissions
Proof of Mutual Exclusion
Predicate A1 bellow is an inductive invariant2.
8
8Vi; eating[i] =) HasToken[i]
>
>
>
>
>
>
>
>
8Vi; j 2 [1 : : : N ]; i 6= j =) (:HasToken[i] _ :HasToken[j ])
>
>
>
>
<
A1 > 8Vi; HasToken[i] =) 8j; T 62 IN [j ]
>
>
>
2
>
>
8j 6= i; T 62 IN [j ]
>
>
>
>
4
^
8
i;
T
2
IN
[
i
]
=
)
>
>
:
8j; :HasToken[j ]
(8.1)
Progress: the ! Graph
Let D be a relation dened between nodes of the network by the following rules:
Node i ! j if and only if one of the following conditions is veried:
D1: Next[i] = j
D2: R [i] 2 IN[j]
D3: Position(ReqList[j],i) = 1
D4: 9 k, Position(ReqList[k],j) = Position(ReqList[k],i) + 1
2
A1 is valid initially, and for every rule R with guard G and action S , fA1 ^ Gg S fA1g.
162
priority
tables
arbiters
clients
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
'$
'$
'$
&% &% &%
'$
'$
'$
&% &% &%
3
1
1r
r
HH
2
1
2
3
2
r
3
r
HH;;
;
;
H
; HHH
;
;
;
HH;
;
HHH
;
;
H
r
r
^
_
Figura 8.7: Client 2 eats
D5: T 2 IN[j], Position(T.ReqList,i) = 1
D6: 9 k, T 2 IN[k], Position(T.ReqList, j) = Position(T.ReqList,i) + 1
Theorem 1
The root node: Let root be a state predicate such that root(i) = TRUE i 6 9
no other node j such that i ! j.
THEOREM 1
A2 There is always one and only one root node, i.e., a node i such that root(i)
= TRUE;
A3 The relation ! always dene one and only one acyclic path from any
non-root node to the root.
We must add A4 and A5 bellow in order to get an inductive invariant:
A4 (HasToken[i] _ T 2 IN[i]) , root(i)
A5 For any non-root node i, there is one and just one node j such that i ! j,
and one and just one condition among D1, . . . , D6 holds between i and j.
Theorem 1: Initial Conditions
A2 ^ A3 ^ A4 ^ A5 hold initially:
~ MUTUA
8.2. EXCLUSAO
DISTRIBUIDA
'$
'$
'$
&% &% &%
'$
'$
'$
&% &% &%
1
3
priority
tables
arbiters
1 r
r
clients
HH
1
2
3
2
2
r
3
r
HH;;
;
;
H
; HHH
;
;
;
HH;
;
HHH
;
;
H
r
r
163
^
Figura 8.8: Client 3 nally eats
Node 1 is the only node that has HasToken = TRUE, and it is the unique
root.
Every node j, j 6= i, ! node 1, since
{ all input channels and ReqLists are initially empty, and thus conditions D2 to D6 do not apply to any node;
{ Next[1] = nil, and Next[2] = Next[3] = : : : Next[N] = 1 initially.
Theorem 1: Scanning the Rules
Now we will show that for every rule R, if A2 ^ A3 ^ A4 ^ A5 and the
enabling predicate hold, then Theorem 1 will hold after the rule's action.
Rules 1 to 3 do not change relation ! , so they trivially verify the
induction step.
The following conventions are used to represent graphically the ! graph:
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
164
a
D2
a
a
b
Node a depends on node b by D2
b
There is a path from a to b
a is the root node
Theorem 1: \Proof" for Rule 4
x
x
i
i
D3
D1
y
a
y
a
D5
D4
z
b
z
b
D4
w
c
D6
w
i’s ReqList
Before Rule 4
c
token ReqList
After Rule 4
Stopping to eat, sending the token
~ MUTUA
8.2. EXCLUSAO
DISTRIBUIDA
165
Theorem 1: \Proof" for Rule 5
i
D1
Next
root
Before Rule 5
x
i
y
D2
Next
z
root
After Rule 5
x
y
Requesting the token;
z
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
166
Theorem 1: \Proof" for Rule 6
x
i
root
D3
y
D2
a
R
b
w
Before Rule 6
D4
z
x
i
root
a
R
D3
y
D4
z
After Rule 6
D4
b
w
Storing a request (Rule 6)
Theorem 1: \Proof" for Rule 7
x
R
x
R
D2
D1
y
i
Before Rule 7
Releasing the token upon request
y
i
After Rule 7
~ MUTUA
8.2. EXCLUSAO
DISTRIBUIDA
167
Theorem 1: \Proof" for Rule 8
D2
D1
R
Next
i
root
Before Rule 8
x
y
z
w
Next
root
D2
D1
R
i
After Rule 8
x
z
y
w
Forwarding a request
Theorem 1: \Proof" for Rule 9
token ReqList
D6
c
b
x
y
i’s ReqList
D6
a
D5
i
D3
r
D4
z
s
s
Before Rule 9
After Rule 9
D4
c
b
D4
D4
a
D3
i
r
D4
s
i’s ReqList
x
y
z
s
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
168
Receiving the token
Progresso
Queremos mostrar que
s[i] = hungry leads-to s[i] = eating
Vamos comecar mostrando que
P 1 s[i] = hungry ^ root(i) leads;to s[i] = eating:
Pelo invariante A4, root(i) =) Hastoken[i] _T 2 IN [i]. E facil ver que (por
hipotese de equidade fraca na execuc~ao da Regra 9)
hungry ^ T 2 IN [i] leads;to Hastoken[i]
Como
hungry ^ Hastoken[i] leads;to s[i] = eating;
temos o resultado que queramos.
Consideremos agora uma computac~ao innita em que um stio i0 estava com
fome em um certo instante t0 , e permaneceu com fome ate o m dos tempos.
Pelo que acabamos de demonstrar, sabemos que no instante t0 tnhamos root(i0 ) =
F , e portanto que para todo instante t t0 , 9j; i0 ! j .
Se no instante t0 tnhamos Next[i] 6= NIL, a regra 5 certamente tera sido
executada em um instante t1 > t0 . Um Request tera sido enviado por i0 .
Este Request n~ao pode ter visitado um numero ilimitado de stios, como veremos
a seguir. Portanto, teremos um stio i1 onde o Request de i tera se estabilizado
a partir de um instante t2 .
Por D3 ou D4 , teremos i ! i1 para todo instante t t2 Isto so e possvel se i1
tambem nunca chegou a comer na computac~ao , a partir do instante t2 .
Pelo mesmo raciocnio, existe um stio i2 que a partir de um certo instante reteve
o Request de i1 , e que nunca chegou a comer.
Portanto, a unica possibilidade de exist^encia de e a exist^encia de uma sequ^encia innita de stios i0; i1 ; i2 ; : : : tal que, a partir de um certo instante, o
Request de ik esteja retido em ik+1 . Mas como ik ! ik+1 , e como D e um
grafo acclico, esta sequ^encia n~ao pode conter repetic~oes, e n~ao pode existir.
Um Request visita um numero nito de stios
Para provar que um Request n~ao pode visitar um numero ilimitado de stios,
vamos demonstrar o seguinte invariante:
~ MUTUA
8.2. EXCLUSAO
DISTRIBUIDA
169
A7 if V [i] = v1 v2 : : : vm , then for j; k 2 [1 : : : m], vj 6= i, and j 6= k =)
vj =
6 vk .
Em outras palavras, todos os elementos em V [i] s~ao distintos, e seu comprimento n~ao pode crescer indenidamente.
A7 n~ao e indutivo, e precisamos reforca-lo com o seguinte predicado:
A8 = j 2 V[i] =) j !+ i
onde j !+ i signica que existe uma rota de j para i de comprimento maior ou
igual a 1 no grafo ! .
Como para todo i V[i] e inicialmente vazio, A8 e valido inicialmente. Precisamos
agora varrer todas as regras do algoritmo, demonstrando que se A8 for valido
antes da execuc~ao da regra, A8 sera valido tambem apos a sua execuc~ao.
A8 corre o risco de ser invalidado por regras que modiquem o valor de algum
V[i] ou que eliminem relac~oes j !+ i para algum par de stios.
Exerccios
Exerccio 8.2.1 (Defasagem de Relogios) Dois computadores que se comu-
nicam por mensagens querem manter seus relogios logicos com uma defasagem
que nunca exceda um certo valor . Faca um algoritmo distribudo para o
controle desdes dois relogios, procurando minimizar o trafego de mensagens e
o tamanho de cada mensagem. Considere que o meio de comunicac~ao nunca
inverte a ordem de envio das mensagens.
Exerccio 8.2.2 (Transmiss~ao de Sequ^encias) Programe um algoritmo pa-
ra transmiss~ao de uma sequ^encia de itens de um computador para outro. Cada
mensagem deve transportar no maximo um item por vez. A sequ^encia de itens
recebidos deve permanecer igual a sequ^encia de itens enviados, ou ter apenas um
item a menos. Considere que o meio de comunicac~ao nunca inverte a ordem de
envio das mensagens, mas que pode perder algumas delas.
Exerccio 8.2.3 (Conta Bancaria) Uma conta bancaria deve ser mantida
por dois computadores; qualquer um deles deve permitir depositos e retiradas.
Programe estas operac~oes de forma a n~ao permitir que o saldo global seja negativo, e que procurando minimizar o trafego de mensagens.
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
170
8.3 2o Trabalho Pratico
Distribuic~ao: 17/11/98
Entrega:
21/12/98
Parte 1: Leia a parte de sockets no tutorial da Sun.
Parte 2: Implemente os algoritmos de Maekawa, Carvalho e Campos e Naimi
e Trehel usando o sistema Voyager3. O sistema deve inicializar em cada uma
das n maquinas um servidor Voyager. Para cada algoritmo, um agente com a
implementac~ao do algoritmo deve ser enviado para cada maquina participante.
Procure fazer uma interface que permita monitorar a instalac~ao e execuc~ao dos
algoritmos.
Informac~oes sobre a instalac~ao Voyager do DCC podem ser obtidas contactandose o Yuri4 no CRC.
8.3.1 Voyager
Voyager5 e um sistema moderno para programac~ao distribuda em Java que
oferece um tipo simples de agentes.
Programas Voyager
Um programa Voyager que executa
Voyager.startup(7000);
Store store = new Store()
associa-se ao porto 7000, e automaticamente dispara threads que
prov^em servicos de temporizaca~o
fazem coleta de lixo distribuda
aceitam trafego na rede
Classes Remotas e Refer^encias Virtuais
Classes Remotas podem ser geradas a partir de classes comuns, utilizando-se
o utilitario vcc, que aplicado sobre Store.java ou Store.class gera a classe remota
VStore.class
3
4
5
htt;://www.objectspace.com
mailto:[email protected]
http://www.objectspace.com
8.3. 2O TRABALHO PRATICO
171
Inst^ancias de Classes Remotas
podem ser criadas fora do espaco de enderecamento de um programa
podem receber mensagens como se fossem locais.
Uma refer^encia virtual e usada para isto.
Se uma classe e remota, pode-se
construir inst^ancias remotas , mesmo se o codigo da classe n~ao existe
na maquina remota
Voyager.startup(7000);
VStore vstore = new VStore("dallas:8000/Loja");
// Loja \'{e} um alias
enviar mensagens para inst^ancias remotas
vstore.stock("widget",43);
estabelecer conex~oes com inst^ancias remotas de outros programas
// conecta usando alias
Voyager.startup(9000);
VStore vstore2 = (VStore) VObject.forObjectAt("dallas:8000/Loja");
int price = vstore2.buy("widget");
mover objetos para outros programas
vstore.moveTo("tokyo:9000");
O objeto espera o processamento das mensagens pendentes e muda-se,
deixando o novo endereco para os que n~ao sabem de sua mudanca
tornar o objeto persistente .
Agentes Voyager
Agentes Voyager s~ao objetos que podem autonomamente decidir sua propria
mudanca
para outras maquinas
public void travel() {
moveTo("tokyo:9000", "atTokio");
}
172
~ DISTRIBUIDA
CAPITULO 8. PROGRAMACAO
\atTokio" e um metodo que sera chamado assim que o agente chegar em
\tokyo:9000".
para outros objetos
public void buyFrom(VStore vstore) {
moveTo(vstore,"shop");
}
o agente se move para a maquina onde esta vstore; ao chegar la, o procedimento shop e chamado.
Tipos de Mensagens
Mensagens, ou chamadas de metodos, podem ter diversos tipos:
sncronas
assncronas (One-Way )
circulares assncronas
futuras
Parte IV
Balanco e Conclus~oes
173
Bibliograa
[Andrews and Schneider, 1983] Andrews, G. R. and Schneider, F. B. (1983).
Concepts and notations for concurrent programming. Computing Surveys,
15:3{43.
[Bal et al., 1989] Bal, H. E., Steiner, J. G., and Tanembaum, A. S. (1989).
Programming languages for distributed computing systems. ACM Computing
Surveys, 21(3).
[Barbara and Garcia-Molina, 1986] Barbara, D. and Garcia-Molina, H. (1986).
Mutual exclusion in partitioned distributed systems. Distributed Computing,
1(1):119{132.
[Bernstein et al., 1987] Bernstein, P. A., Hadzilacos, V., and Goodman, N.
(1987). Concurrency Control and Recovery in Database Systems. AddisonWesley, Reading.
[Bitton et al., 1984] Bitton, D., DeWitt, D. J., Hsiao, D. K., and Menon, J.
(1984). A taxonomy of parallel sorting. ACM Computing Surveys, 16(3):287{
318.
[Campbell and Habermann, 1974] Campbell, R. H. and Habermann, A. N.
(1974). The specication of process synchronization by path expressions, volume 16 of Lecture Notes in Computer Science. Springer Verlag.
[Carvalho and Roucairol, 1983] Carvalho, O. S. F. and Roucairol, G. (1983).
On mutual exclusion in computer networks. Communications of the ACM,
26(2).
[Chandy and Misra, 1984] Chandy, K. M. and Misra, J. (1984). The drinking
philosophers problem. ACM Transactions on Programming Languages and
Systems, 6(4).
[de Aguiar Campos and Carvalho, 1988] de Aguiar Campos, S. V. and Carvalho,
O. S. F. (1988). Um algoritmo distribudo para exclus~ao mutua com
o(pn) mensagens. In Anais do 6o Simposio Brasileiro de Redes de Computadores, PortoAlegre. Sociedade Brasileira de Computac~ao.
175
176
BIBLIOGRAFIA
[Dijkstra, 1965a] Dijkstra, E. W. (1965a). Co-operating Sequential Processes.
Academic Press, London.
[Dijkstra, 1965b] Dijkstra, E. W. (1965b). Solution of a problem in concurrent
programming control. Communications of the ACM, 8(9):569.
[Dijkstra, 1975] Dijkstra, E. W. (1975). Guarded commands, nondeterminacy
and formal derivation of programs. Communications of the ACM, 18(8):453{
457.
[Dinning, 1989] Dinning, A. (1989). A survey of synchronization methods for
parallel computers. Computer, 22(7):66{77.
[Dubois et al., 1988] Dubois, M., Scheurich, C., and Briggs, F. A. (1988). Synchronization, coherence, and event ordering in multiprocessors. Computer,
21(2):9{21.
[Eswaran et al., 1976] Eswaran, K. P., Gray, J. N., Lorie, R. A., and Traiger,
I. L. (1976). The notions of consistency and predicate locks in a database
system. Communications of the ACM, 19(11).
[Floyd, 1967] Floyd, R. W. (1967). Assigning meaning to programs. In
Schwartz, J. T., editor, Mathematical aspects of computer science: Proc.
American Mathematics Soc. symposia, volume 19, pages 19{31, Providence
RI. American Mathematical Society.
[Gray and Reuter, 1993a] Gray, J. and Reuter, A. (1993a). Transaction Processing: Concepts and Techniques. Morgan Kaufmann Publishers, San Mateo,
CA.
[Gray and Reuter, 1993b] Gray, J. and Reuter, A. (1993b). Transaction Processing: concepts and techniques. Morgan Kaufmann Publishers, Inc.
[Hansen, 1972] Hansen, P. B. (1972). Concurrent programming concepts. ACM
Computing Surveys, 5:233{245.
[Hoare, 1969] Hoare, C. A. R. (1969). An axiomatic basis for computer programming. Communications of the ACM, 12(10):576{580.
[Hoare, 1974] Hoare, C. A. R. (1974). Monitors, an operating system structuring concept. Communications of the ACM, 17(10):549{557.
[Hoare, 1978] Hoare, C. A. R. (1978). Communicating sequential processes.
Communications of the ACM, 21(8):666{677.
[Johnson and Shasha, 1993] Johnson, T. and Shasha, D. (1993). The performance of concurrent B-Tree algorithms. ACM Transactions on Database
Systems, 18(1):51{101.
[Keller, 1976] Keller, R. M. (1976). Formal verication of parallel programs.
Communications of the ACM, 19(7).
BIBLIOGRAFIA
177
[Knuth, 1966] Knuth, D. E. (1966). Additional comments on a problem in
concurrent programming control. Communications of the ACM, 9(5):321{
322. Letter to the editor.
[Kohler, 1981] Kohler, W. H. (1981). A survey of techniques for synchronization
and recovery in decentralized computer systems. ACM Computing Surveys,
13(2).
[Lakshman and Agrawala, 1986] Lakshman, T. V. and Agrawala, A. K. (1986).
Ecient decentralized consensus protocols. IEEE Transactions on Software
Engineering, SE-12(5):600{607.
[Lamport, 1978] Lamport, L. (1978). Time, clocks, and the ordering of events
in a distributed system. Communications of the ACM, 21(7).
p
[Maekawa, 1985] Maekawa, M. (1985). A n algorithm for mutual exclusion in
decentralized systems. ACM Transactions on Computing Systems, 3(2).
[Manna and Pnueli, 1981] Manna, Z. and Pnueli, A. (1981). Verication of
concurrent programs: Temporal proof principles. In Kahn, G., editor, Logics
of Programs, volume 131 of LNCS, pages 200{252. Springer-Verlag , Berlin,
Germany.
[Milner, 1984] Milner, R. (1984). Lectures on a Calculus for Communicating
Systems, volume 197 of LNCS. Springer-Verlag, New York, NY.
[Naimi and Trehel, 1987] Naimi, M. and Trehel, M. (1987). An improvement
of the log N distributed algorithm for mutual exclusion. In 7th International
Conference on Distributed Computing Systems, pages 371{377, Washington,
D.C., USA. IEEE Computer Society Press.
[Owick and Gries, 1976] Owick, S. and Gries, D. (1976). Verifying properties
of parallel programs: an axiomatic approach. Communications of the ACM,
19(5).
[Pnueli, 1979] Pnueli, A. (1979). The temporal semantics of concurrent programs. In Kahn, G., editor, Semantics of Concurrent Computations, volume 70 of LNCS, pages 1{20, Evian, France. Springer-Verlag , Berlin, Germany.
[Ricart and Agrawala, 1981] Ricart, G. and Agrawala, A. K. (1981). An optimal
algorithm for mutual exclusion in computer networks. Communications of the
ACM, 24(1).
[Shankar, 1993] Shankar, A. U. (1993). An introduction to assertional reasoning
for concurrent systems. ACM Computing Surveys, 25(3):225{262.
[Tanenbaum, 1987] Tanenbaum, A. S. (1987). Operating Systems Design Implemtations. Prentice-Hall.
Indice Remissivo
Avaliac~ao, 14
cobegin, 18
coend, 18
Conitos, 21
Ementa, 12
Grafo de Preced^encias, 19
Lamport, 103
Links, 15
Modelo de Programac~ao, 16
Modo de execuc~ao, 16
Programac~ao Paralela Assncrona, 16
Sem^antica de Programas Paralelos,
21
Sem^antica n~ao-determinstica, 22
Sem^antica sequencial, 22
178
Download