Sop Progconctext
Sop Progconctext
Sop Progconctext
programa.Mesmoemsistemascomumnicoprocessador,existemrazesparaoseuusoem
vriostiposdeaplicaes.
Considereumprogramaquedevelerregistrosdeumarquivo,colocaremumformato
apropriadoeentoenviarparaumaimpressorafsica(emoposioaumaimpressoralgicaou
virtual, implementada comarquivos). Podemos fazerissocom umprograma seqencial que,
dentrodeumlao,fazastrsoperaes(ler,formatareimprimirregistro).
Arquivo
Processo
Impressora
fsica
Figura1Programaseqencialacessandoarquivoeimpressora.
Inicialmenteoprocessoenviaumcomandoparaaleituradoarquivoeficabloqueado.O
disco ento acionado para realizar a operao de leitura. Uma vez concluda a leitura, o
processorealizaaformataoeiniciaatransfernciadosdadosparaaimpressora.Comotratase
deumaimpressorafsica,oprocessoexecutaumlaonoqualosdadossoenviadosparaaporta
serialouparalelaapropriada.Comoobufferdaimpressorarelativamentepequeno,oprocesso
ficapresoatofinaldaimpresso.Odiscoeaimpressoranuncatrabalhamsimultaneamente,
emboraissosejapossvel.oprogramaseqencialquenoconsegueocuparambos.
Vamosagoraconsiderarumprogramaconcorrentecomoomostradonafigura2para
realizar a impresso do arquivo. Dois processos dividem o trabalho. O processo leitor
responsvel por ler registros do arquivo, formatar e colocar em um buffer na memria. O
processoimpressorretiraosdadosdo buffer eenviaparaaimpressora.supostoaquiqueos
doisprocessospossuemacessomemriaondeesto buffer. Esteprogramamaiseficiente,
poisconseguemanterodiscoeaimpressoratrabalhandosimultaneamente.Otempototalpara
realizaraimpressodoarquivovaisermenor.
Arquivo
Processo
Leitor
Buffer
Processo
Impressor
Impressora
fsica
Figura2Programaconcorrenteacessandoarquivoeimpressora.
Ousodaprogramaoconcorrentenaturalnasaplicaesqueapresentamparalelismo
intrnseco, ditas aplicaes inerentemente paralelas. Nessas aplicaes podese distinguir
PROGRAMAO CONCORRENTE Prof. Simo Toscani
(Do livro Sistemas Operacionais e Programao Concorrente, Toscani S.S., Oliveira R.S. e Carissimi A.S.
Editora Sagra-Luzzatto, 2003)
facilmentefunesparaseremrealizadasemparalelo.Esteocasodospoolingdeimpresso,
exemploqueserapresentadoaseguir.Podesedizerque,emgeral,aprogramaoconcorrente
temaplicaonaturalnaconstruodesistemasquetenhamdeimplementarserviosqueso
requisitados de forma imprevisvel [DIJ65]. Nesse caso, o programa concorrente ter um
processopararealizarcadatipodeservio.
Aseguirconsideradoumservidordeimpressoparaumaredelocal.Afigura3ilustra
umaredelocalnaqualexistemdiversoscomputadorespessoais(PC)utilizadospelosusuriose
existeumcomputadordedicadoaopapeldeservidordeimpresso.Oservidorusaumdisco
magnticoparamanterosarquivosqueestonafiladeimpresso.
PC
Usurios
PC
PC
Servidor de Impresso
Figura3Redelocalincluindoumservidordeimpressodedicado.
disco.Quandoopedaodearquivoemquestooltimodeseuarquivo,oprocesso"Escritor"
passaparaoprocesso"Leitor"onomedoarquivo,queestprontoparaserimpresso.
Receptor
Transmissor
Protocolo
Escritor
Leitor
Impressor
Figura4Servidordeimpressocomoprogramaconcorrente.
Oprocesso"Leitor"executa umlaonoqualelepegaumnomedearquivo,enviao
contedodoarquivoparaoprocesso"Impressor"eentoremoveoarquivolido.Oenviodo
contedoparaoprocesso"Impressor"feitoatravsdeumlaointernocompostopelaleiturade
umapartedoarquivoepeloenviodessaparte.Finalmente,oprocesso"Impressor"encarregado
deenviarospedaosdearquivoqueelerecebeparaaimpressora.Orelacionamentoentreos
processos"Leitor"e"Escritor"foidescritoantes,noinciodestaseo.
Oservidordeimpressoilustraoempregodaprogramaoconcorrentenaconstruode
umaaplicaocomparalelismointrnseco.Oresultadoumaorganizaointernaclaraesimples
para o programa. Um programa seqencial equivalente seria certamente menos eficiente. O
restantedestecaptulodedicadoaosproblemasestcnicasexistentesparaaconstruode
programasconcorrentescomoesse.
Hojeemdiaexistemvriaslinguagensquepermitemconstruirprogramasconcorrentes
(Java,Ada,PascalConcorrente,Cestendidocombibliotecasparaconcorrncia,etc.).Aquiser
utilizadaumalinguagemapropriadaparaensino,denominadaVale4(V4)[TOS04].
3 Especificao do paralelismo
Para construir um programa concorrente, antes de mais nada, necessrio ter a capacidade de
especificar o paralelismo dentro do programa. Essa especificao pode ser feita de diversas
maneiras. Uma delas utiliza os comandos fork, quit e join [CON63]. Outras maneiras sero
apresentadas na seo 4.
O comando (ou funo) fork pode ser implementado de duas maneiras distintas: ele pode
criar um novo processo ou criar apenas um novo fluxo de execuo dentro de um processo j
existente. A funo fork retorna um nmero inteiro que a identificao do novo processo ou do
novo fluxo criado. Um fluxo de execuo tambm denominado linha de execuo ou thread.
Os comandos quit e join so auxiliares ao fork. Quando o comando quit executado, o
processo (ou thread) que o executa termina imediatamente. O comando join(id) bloqueia quem o
executa at que termine o processo (ou thread) identificado por id.
Primitiva fork no sistema Unix
No sistema operacional Unix a operao fork cria um novo processo que uma cpia idntica
(clone) do processo que executa esta operao. Por exemplo, o comando
id = fork()
cria um filho idntico ao processo que executou a operao (isto , cria uma cpia do processo
original). O processo filho recebe cpias das variveis do processo pai, bem como dos descritores
de arquivos. Os valores iniciais das variveis do filho so iguais aos valores das variveis
correspondentes do pai no momento da execuo da funo fork. Observe que no h
compartilhamento de variveis: as variveis do pai ficam no espao de endereamento1 do pai e as
variveis do filho, no espao de endereamento do filho. Em relao aos valores dessas variveis,
a nica diferena inicial entre o pai e o filho o valor da varivel id, que 0 para o filho e o
valor de retorno da funo fork para o pai. O valor de retorno o nmero de identificao do
processo criado (process identification ou pid). Isto permite que os processos prossigam de
acordo com suas identidades. Normalmente, o comando seguinte ao fork tem a seguinte forma:
if id = 0
then { processamento do filho }
else { processamento do pai }
Um dos processos, por exemplo o filho, pode sobrepor um novo cdigo sobre si, atravs
da operao exec(P), onde P um novo programa para ser executado (novo segmento de cdigo
e de dados para o processo).
Fork, join e quit na linguagem Vale4
Na linguagem Vale4, o funcionamento do comando fork similar ao do Unix, porm com uma
grande diferena: o fork cria uma thread e no um processo. As threads me e filha so idnticas:
executam o mesmo cdigo e compartilham todas as variveis do processo em que so definidas (
justamente nesse compartilhamento que est a diferena para o Unix).
Na linguagem V4, a execuo do comando
id := fork()
faz com que a varivel global2 id receba o valor retornado pela funo fork, que o nmero nico
da thread criada. A thread original (me) e a thread criada (filha) executam em paralelo a partir do
1
comando que segue ao fork. As duas threads iro se distinguir atravs da varivel denominada
myNumber3. O valor dessa varivel sempre a identificao de quem a refere (isto , o nmero
nico de quem a refere). Tipicamente, o comando que segue ao fork tem a seguinte forma:
if id = myNumber
then { processamento da filha }
else { processamento da me }
Observe que apenas para a thread filha o myNumber igual ao valor da varivel global id.
Para criar processos (no threads) dinamicamente, a linguagem V4 oferece o comando
new que ser apresentado na seo que segue. Enquanto o comando fork cria uma nova thread, o
comando new cria um novo processo.
O comando join(id) permite que um processo (ou thread) P espere pelo trmino do
descendente imediato (filho ou filha) identificado por id. Se o argumento id no identifica um
processo ou thread, ou se id no corresponde a um descendente imediato de P, ento um erro
reportado (erro de execuo).
O argumento de join pode ser tambm a palavra reservada any, que significa o desejo de
esperar pelo trmino de qualquer um dos descendentes imediatos. Nesse caso, no retorno da
primitiva, a varivel any4 vai conter a identidade do filho ou filha cuja execuo terminou.
Outra peculiaridade da primitiva join(id) que ela pode ser usada como funo ou como
subrotina. Usada como funo, ela retorna o valor que o filho (ou filha) id especificou no
comando quit, ao morrer, conforme explicado a seguir.
O ltimo comando do conjunto o quit, que mata o seu executor. Podem ser usadas as
formas quit ou quit(X). No segundo caso, o argumento X um valor inteiro que o processo ou
thread informa ao seu genitor, ao morrer. Se desejar pegar esse valor, o genitor usar a primitiva
join, como funo.5 A propsito, um quit sem argumento equivale a um quit(0).
Diferena entre thread e processo
mais fcil chavear a execuo entre threads (de um mesmo processo) do que entre
processos, pois tem-se menos informaes para salvar e restaurar. Por esse motivo, as threads so
chamadas tambm de "processos leves".
Um exemplo
VamosusaralinguagemV4paraexemplificarousodoscomandosfork,joinequit.Oprograma
mostradonafigura5possuium nicoprocesso.Alinhadeexecuo inicial desseprocesso
executaduasvezesocomando fork,criandoduas threads adicionais (filhas1e2).A thread
originalentoesperaquecadaumadasfilhastermine,escreveumamensagemparacadaumae
terminatambm.Asduasthreadscriadasapenascolocamumamensagemnatelaeterminam.
V4program
process p1;
f1: integer;
f2: integer;
/* Cria filha 1 */
/* Cria filha 2 */
Alo da mae
Alo do filha 1
Filha 1 morreu
Alo do filha 2
Filha 2 morreu
Neste caso, cada processo especificado de forma individual, conforme exemplificado a seguir.
V4program
process P1;
k: integer init 0;
while k < 10 do
{ write(1);
k:=k+1
};
process P2;
k: integer init 0;
while k < 10 do
{ write(2);
k:=k+1
}
endprogram
O programa define 2 processos, denominados P1 e P2, que no compartilham variveis
(no existem variveis globais no programa). Cada processo utiliza uma varivel local,
denominada k. O primeiro imprime 10 vezes o nmero 1 e o segundo, em paralelo, imprime 10
vezes o nmero 2. O resultado da execuo pode ser qualquer seqncia de tamanho 20, contendo
10 vezes o nmero 1 e 10 vezes o nmero 2, embaralhados. Teoricamente, so possveis 20!/(10!
*10!) resultados diferentes.8
Por exemplo, se a execuo no passa por uma determinada instruo fork, ento a thread correspondente no
criada.
7
A declarao explcita consiste em definir, para cada processo do programa, as suas variveis locais e o seu
segmento de cdigo.
8
Combinaes de uma seqncia de 20 escaninhos, escolhidos 10 a 10.
Array de processos
Neste caso, uma nica declarao especifica um grupo de processos semelhantes, que se
distinguem apenas pelo valor de uma varivel local inteira, que especificada no cabealho do
processo, conforme ilustrado a seguir, considerando o mesmo exemplo anterior.
V4program
process P (i := 1 to 2);
k: integer init 0;
while k < 10 do
{ write(i);
k:=k+1
}
endprogram
Para o primeiro processo, a sua varivel local i vale 1 e para o segundo, a sua varivel
local i vale 2. Este programa equivalente ao anterior.
Criao dinmica
possvel declarar explicitamente um modelo (uma "forma") para criar processos durante a
execuo, conforme ilustrado a seguir. Neste caso tem-se o que se denomina criao dinmica
com declarao explcita de processos.
V4program
process type P (i: integer);
k: integer init 0;
while k < 10 do
{ write(i);
k:=k+1
};
process Q;
{ new P(1); new P(2) }
endprogram
Atravs da especificao process type, explicita-se um modelo (template) de processo, o
qual utilizado para criar exemplares (cpias, clones) desse processo durante a execuo. A
criao de um novo exemplar se d atravs do comando new, o qual permite passar parmetros
para o processo criado. No caso da linguagem Vale4, a primitiva new pode ser usada como funo
ou como subrotina; usada como funo ela retorna a identificao interna (pid) do processo
criado.
5 Exemplos de programas concorrentes
Esta seo apresenta programas simples que ilustram caractersticas importantes dos programas
concorrentes. Tratam-se de programas Vale4 completos, prontos para serem compilados e
PROGRAMAO CONCORRENTE Prof. Simo Toscani
(Do livro Sistemas Operacionais e Programao Concorrente, Toscani S.S., Oliveira R.S. e Carissimi A.S.
Editora Sagra-Luzzatto, 2003)
executados no ambiente V4. Para melhorar a legibilidade dos programas, usada a seguinte
notao: os identificadores declarados (variveis, procedimentos, etc.) so apresentados em
itlico.
Compartilhamento de um procedimento
O mesmo programa que foi utilizado na seo 3.5 para distinguir as diferentes maneiras de
especificar (e criar) processos reescrito para ilustrar o compartilhamento de um procedimento.
V4program
procedure imprime(i: integer);
k: integer init 0;
while k < 10 do
{ write(i);
k:=k+1
};
process P1; imprime(1);
process P2; imprime(2)
endprogram
Cada processo chama imprime fornecendo como argumento o nmero a ser impresso.
Como nos exemplos anteriores, o resultado da execuo desse programa imprevisvel, sendo
10
possveis (teoricamente) C 20
resultados distintos.
Observao sobre as variveis de um procedimento
O programa a seguir implementa um sistema concorrente onde dois processos compartilham uma
varivel global S. Cada processo incrementa S de uma unidade, 100 vezes.
V4program
S : integer init 0;
process p1;
PROGRAMAO CONCORRENTE Prof. Simo Toscani
(Do livro Sistemas Operacionais e Programao Concorrente, Toscani S.S., Oliveira R.S. e Carissimi A.S.
Editora Sagra-Luzzatto, 2003)
10
k: integer init 0;
{ loop
S:= S+1;
k:= k+1;
exit when k = 100
endloop;
nl; write('p1'); tab(2); write(S)
};
process p2;
k: integer init 0;
{ loop
S:= S+1;
k:= k+1;
exit when k = 100
endloop;
nl; write('p2'); tab(2); write(S)
}
endprogram
Este programa utiliza os comandos loop e tab(K), os quais so explicados a seguir.
O comando loop
O comando loop implementa um ciclo infinito. No seu interior, o comando exit when <cond>
significa que o ciclo acaba (isto , que a execuo vai para o comando seguinte ao endloop)
quando a condio <cond> verdadeira. Este comando pode substituir todos os demais comandos
iterativos (while, repeat, for, etc.), com a vantagem de, em geral, tornar os programas mais claros.
O comando tab(K)
Este comando escreve K espaos em branco no terminal do usurio, sendo til para formatar a
impresso de resultados.
Observao sobre a inicializao de variveis
push
$1
add
11
pop
% guarda o resultado em S
Como os pontos em que a UCP passa de um processo para outro so imprevisveis, pode
acontecer de um processo perder a UCP no meio da seqncia acima.9 Vamos supor que o valor
de S carregado na pilha seja 10 e que o processo perca a UCP. Nesse caso, quando este processo
receber a UCP de volta, ele vai concluir a seqncia acima e armazenar o valor 11 em S. Todos os
acrscimos a S feitos pelo outro processo nesse nterim so perdidos. Como conseqncia,
embora S inicie com o valor zero e cada processo some 1 a S cem vezes, o valor final de S
dificilmente ser igual a 200. Para o resultado ser 200, deve haver excluso mtua no acesso
varivel S, isto , enquanto um processo estiver manipulando S, o outro no pode acessar S.
A excluso mtua um requisito muito importante nos sistemas concorrentes. Em geral,
necessrio garantir o acesso exclusivo aos dados compartilhados. A excluso mtua s no
necessria quando os dados so compartilhados na modalidade "apenas leitura", isto , quando os
dados no so alterados pelos processos. Os trechos dos processos onde os dados compartilhados
so manipulados, so denominados trechos crticos ou regies crticas.
Criao dinmica de processos
Sempre que um processo perde a UCP, o seu estado salvo. Mais tarde, a execuo do processo continua, como se
nada tivesse acontecido.
12
Um processo s entra num trecho delimitado pelo par lock/unlock se nenhum outro processo est
executando em um outro trecho delimitado dessa maneira. Isto , o primeiro processo que executa
o comando lock passa e tranca a passagem (chaveia a fechadura) para os demais. O comando
unlock deixa passar (desbloqueia) o primeiro processo da fila de processos que esto bloqueados
por terem executado um lock (enquanto a fechadura estava trancada). Se a fila est vazia, a
fechadura destrancada (isto , deixada aberta).
block/wakeup(P)
Quando um processo P executa o comando block, ele se bloqueia at que um outro processo
execute o comando wakeup(P). Este ltimo comando acorda (desbloqueia) o processo
especificado por P. Se wakeup(P) executado antes, o processo P no se bloqueia ao executar o
block. Na linguagem Vale4, o argumento de wakeup pode ser um nome de processo ou um
nmero nico de processo ou thread.
Na verdade, os comandos lock e unlock no formam uma estrutura sinttica (isto , no
precisam estar casados, como se fossem um abre e fecha parnteses), eles so comandos
independentes. Na linguagem Vale4, as operaes lock e unlock tambm podem ser referidas pelos
nomes mutexbegin e mutexend, respectivamente.
7 Semforos
As variveis semforas so variveis especiais que admitem apenas duas operaes, denominadas
P e V.11 Sendo S uma varivel semfora, as operaes P e V tm a seguinte semntica:
P(S) : espera at S ser maior que 0 e ento subtrai 1 de S;
10
13
V(S) : incrementa S de 1.
As operaes testar S e subtrair 1 (se S > 0) e incrementar S de 1 so executadas de
forma atmica (indivisvel), no kernel do SO. Se S = 1 e dois processos executam P(S)
simultaneamente, um dos processos vai ficar bloqueado.
Pode-se fazer analogia entre uma varivel semfora e um vaso contendo bolitas (bolinhas
de gude). O valor numrico do semforo corresponde ao nmero de bolitas dentro do vaso. Uma
operao V corresponde a pr uma bolita no vaso. Cada operao P tenta remover uma bolita; se
nenhuma est disponvel, ento a operao bloqueia o processo e o coloca numa fila de espera.
Quando uma bolita colocada no vaso (operao V), ela removida pelo primeiro processo da
fila de espera, o qual prossegue sua execuo.
Sincronizaes bsicas com semforos
A sincronizao do tipo excluso mtua implementada atravs de um semforo com valor inicial
1. O acesso exclusivo a n regies crticas seria implementado como segue:
X : semaphore initial 1
P1:
...
P2:
...
...
Pn:
...
P(X);
P(X);
P(X);
REGIO CRTICA;
REGIO CRTICA;
REGIO CRTICA;
V(X);
...
V(X);
...
V(X);
...
Este tipo de sincronizao implementado atravs de um semforo com valor inicial zero. Por
exemplo, se a operao B do processo P1 deve ser executada aps a operao A do processo P2,
programa-se da seguinte maneira:
Y : semaphore initial 0
P1:
...
P(Y);
B;
...
...
P2:
...
% block
...
A;
V(Y); % wakeup(P1)
...
14
8 Programas clssicos
Esta seo apresenta 4 problemas clssicos da programao concorrente, todos resolvidos atravs
do uso de semforos e todos escritos de acordo com a sintaxe de Vale4.
Produtor-consumidor com buffer limitado
Este problema pode ser enunciado como segue. Um par de processos compartilha um buffer de N
posies. O primeiro processo, denominado produtor, passa a vida a produzir mensagens e a
coloc-las no buffer. O segundo processo, denominado consumidor, passa a vida a retirar
mensagens do buffer (na mesma ordem em que elas foram colocadas) e a consum-las.
A relao produtor-consumidor ocorre comumente em sistemas concorrentes e o problema
se resume em administrar o buffer que tem tamanho limitado. Se o buffer est cheio, o produtor
deve se bloquear, se o buffer est vazio, o consumidor deve se bloquear. A programao desse
sistema com buffer de 5 posies e supondo que as mensagens sejam nmeros inteiros, mostrada
a seguir.
Variveis globais:
Processo produtor:
msg, in : integer;
loop
% produz mensagem msg
P(vazios);
in:= (in mod 5)+1;
buffer[in]:= msg;
V(cheios)
endloop
Processo consumidor:
msg, out : integer;
loop
P(cheios);
out:= (out mod 5)+1;
msg:= buffer[out];
V(vazios);
% consome a mensagem
endloop
O semforo cheios conta o nmero de buffers cheios e o semforo vazios conta nmero de
buffers vazios. Conforme j foi referido, as variveis inteiras que no so inicializadas tem seu
valor inicial igual a zero.
Observe que a soluo no se preocupou em garantir excluso mtua no acesso ao buffer.
Isto porque os dois processos trabalham com variveis locais in, out e msg e, certamente, iro
acessar sempre posies diferentes do vetor global buffer.
Jantar dos Filsofos
Este problema ilustra as situaes de deadlock e de postergao indefinida que podem ocorrer em
sistemas nos quais processos adquirem e liberam recursos continuamente.
Existem N filsofos que passam suas vidas pensando e comendo. Cada um possui seu
lugar numa mesa circular, em cujo centro h um grande prato de spaghetti. A figura 6 ilustra a
situao para 5 filsofos. Como a massa muito escorregadia, ela requer dois garfos para ser
PROGRAMAO CONCORRENTE Prof. Simo Toscani
(Do livro Sistemas Operacionais e Programao Concorrente, Toscani S.S., Oliveira R.S. e Carissimi A.S.
Editora Sagra-Luzzatto, 2003)
15
comida. Na mesa existem N garfos, um entre cada dois filsofos, e os nicos garfos que um
filsofo pode usar so os dois que lhe correspondem (o da sua esquerda e o da sua direita). O
problema consiste em simular o comportamento dos filsofos procurando evitar situaes de
deadlock (bloqueio permanente) e de postergao indefinida (bloqueio por tempo indefinido).
filsofo 3
garfo 3
filsofo 4
garfo 2
filsofo 2
spaghetti
garfo 1
garfo 4
filsofo 1
filsofo 5
garfo 5
% array global
16
17
Processo barbeiro:
Loop
P(clientes); /*dorme, se for o caso*/
P(mutex);
count:= count 1;
V(fila); /*pega prximo cliente*/
V(mutex);
Processo cliente:
P(mutex);
if count < 3
then { count:= count+1;
V(clientes); /*acorda o barbeiro*/
V(mutex);
P(fila);
/*espera o barbeiro*/
/*corta o cabelo*/
Endloop
/*corta o cabelo*/
}
else V(mutex)
Quando termina o corte de cabelo, o cliente deixa a barbearia e o barbeiro repete o seu
loop onde tenta pegar um prximo cliente. Se tem cliente, o barbeiro faz outro corte. Se no tem,
o barbeiro dorme.
18
Leitores e escritores
O problema dos readers and writers [COU71] ilustra outra situao comum em sistemas de
processos concorrentes. Este problema surge quando processos executam operaes de leitura e
de atualizao sobre um arquivo global (ou sobre uma estrutura de dados global). A sincronizao
deve ser tal que vrios readers (isto , processos leitores, que no alteram a informao) possam
utilizar o arquivo simultaneamente. Entretanto, qualquer processo writer deve ter acesso exclusivo
ao arquivo.
Na soluo a seguir dada prioridade para os processos readers. So utilizadas duas
variveis semforas, mutex e w, para excluso mtua, e uma varivel inteira nr, para contar o
nmero de processos leitores ativos. Note que o primeiro reader bloqueia o progresso dos writers
que chegam aps ele, atravs do semforo w. Enquanto houver reader ativo, os writers ficaro
bloqueados.
Variveis globais:
Processo leitor:
...
P(mutex);
nr:=nr+1;
if nr=1 then P(w);
V(mutex);
Processo escritor:
...
...
P(w);
READ
P(mutex);
nr:=nr-1;
if nr=0 then V(w);
V(mutex);
WRITE
V(w);
...
...
...
19
EXERCCIOS
1. Um semforo binrio um semforo cujo valor pode ser 0 ou 1. Mostre como um semforo
geral pode ser implementado a partir de semforos binrios.
2. Considere a instruo TS(X,L) que executa o seguinte cdigo de forma indivisvel:
if X then go to L else X:=true;
Mostre como implementar as operaes P e V sobre um semforo binrio usando a instruo
TS.
3. Usando semforos, complete o programa Vale4 a seguir, de maneira que o resultado impresso
seja sempre "AAAAABBBBB" (isto , cada processo s pode imprimir 'B' depois de todos os
outros terem impresso 'A').
V4program
...
process P (i := 1 to 5);
...
{ ...
write('A');
...
write('B');
...
}
endprogram
4. Usando a linguagem V4 e variveis semforas, escreva um programa formado por 6 processos
p1, p2, ..., p6, onde pi (1 i 6) imprime 10 vezes o nmero i. Os processos devem estar
sincronizados de acordo com o grafo de fluxo de processos abaixo:
I
p1
p4
p5
p2
p3
p6
F
20
21
BIBLIOGRAFIA
[CON63] CONWAY, M. E. A Multiprocessor system design. Proc. AFIPS Fall Joint Computer
Conference, pp.139-146. Las Vegas, Nevada, 1963.
[COU71] COURTOIS, P. J., HEYMANS, F.and PARNAS, D. L. Concurrent Control with
Readers and Writers. Comm. ACM 14, No. 10 (October), 667-668, 1971.
[DIJ65]
[SHA84]
[TAF97]
[TOS03]
[TOS04]
22