• Nenhum resultado encontrado

Programação Concorrente na Linguagem Vale 4

N/A
N/A
Protected

Academic year: 2021

Share "Programação Concorrente na Linguagem Vale 4"

Copied!
41
0
0

Texto

(1)

Programação Concorrente

Programação Concorrente

na Linguagem Vale 4

na Linguagem Vale 4

Pontifícia Universidade Católica do Rio Grande do Sul

Pontifícia Universidade Católica do Rio Grande do Sul

PUCRS

PUCRS

Centro Universitário

Centro Universitário

La

La

Salle

Salle

UNILASALLE

UNILASALLE

por

por

Simão Sirineo Toscani

Simão Sirineo Toscani

VII Simpósio Brasileiro de

VII Simpósio Brasileiro de

Linguagens de Programação

Linguagens de Programação

SBLP 2003

SBLP 2003

Ouro Preto

(2)

Introdução (1)

Introdução (1)

Iremos apresentar

Uma linguagem de programação para uso acadêmico

Construída usando software livre (

SWI-Prolog

)

Que pode ser instalada em qualquer microcomputador

Os exemplos são programas completos, prontos para

serem executados.

O ambiente de programação V4

É formado por

um compilador

uma máquina virtual

Trata-se de um ambiente completo para construção e

depuração de programas concorrentes.

(3)

Introdução (2)

Introdução (2)

Programa concorrente

É um programa que origina processos concorrentes

(paralelos) durante sua execução. Estes processos

interagem através de mecanismos apropriados,

normalmente implementados no kernel do SO.

A técnica da programação concorrente foi usada

originalmente na construção de sistemas operacionais.

(4)

Motivação para a criação da linguagem (1)

Motivação para a criação da linguagem (1)

Os profissionais da computação devem dominar as

técnicas e ferramentas usadas na construção de

programas concorrentes.

Não há uma linguagem adequada para esse tipo de

ensino.

O ideal seria que o estudante pudesse aprender a

solucionar os problemas clássicos usando todas as

ferramentas descritas na literatura.

(5)

Motivação para a criação da linguagem (2)

Motivação para a criação da linguagem (2)

Os problemas clássicos:

1. Produtor-consumidor

(relação de cooperação)

2. Jantar dos filósofos

(relação de competição)

3. Barbeiro dorminhoco

(relação cliente-servidor)

4. Leitores e escritores

(situação comum em banco de dados)

As principais ferramentas:

1. Semáforos

2. Monitores

3. Operações send e receive

4. Rendezvous

(6)

A linguagem Vale 4

A linguagem Vale 4

Implementa quase todas as ferramentas e

paradigmas da programação concorrente

Sintaxe simples(*) e semântica clara

Facilidades para depuração (visualização da

execução)

É implementada por

um compilador

uma máquina virtual

(7)

O compilador V4

O compilador V4

Tradu

Tradu

çã

çã

o dirigida por sintaxe.

o dirigida por sintaxe.

O resultado da compila

O resultado da compila

çã

çã

o

o

é

é

:

:

Uma tabela de s

Uma tabela de s

í

í

mbolos (TS) e

mbolos (TS) e

(8)

O simulador V4

O simulador V4

A partir da TS, o simulador da máquina virtual

gera estruturas e faz a execução do código.

Estruturas de dados:

Variáveis inteiras, variáveis booleanas

Arrays de até duas dimensões

Registros descritores de processos

Filas, semáforos

Filas de monitores, variáveis tipo condition

(9)

O ambiente de execução V4

O ambiente de execução V4

O compilador:

O compilador:

repeat,

repeat,

leToken(X),

leToken(X),

colocaNaPilha

colocaNaPilha

(X),

(X),

trataPilha

trataPilha

until

until

X =

X =

endprogram

endprogram

O simulador:

O simulador:

gera estruturas de dados,

gera estruturas de dados,

repeat,

repeat,

selecionaThread(T),

selecionaThread(T),

if T>0

if T>0

then

then

executa T

executa T

until

until

T =

T =

-

-

1,

1,

write

(10)

Os

Os

tokens

tokens

da linguagem V4

da linguagem V4

:= : ; , ( ) [ ] { } ' + - * / mod

& and | or ¬ not %

/* */

integer boolean init queue semaphore array

procedure returns while do forever if then else

loop endloop exit when inline process task

thread fork join quit mutexbegin mutexend

block wakeup P V yield hold monitor

condition priority wait signal initially empty

count first insert send receive entry accept

read write nl tab debug1 debug2 nodebug pause

nothing myself getId random clockTime end

identificadores const_inteiras const_booleanas

(11)

Os comandos da linguagem

Os comandos da linguagem

• Var := EA • P ( Sem ) • if EL then C1 else C2 • V ( Sem ) • while EL do C • yield

• do forever C • hold ( Time ) • loop C1; C2; ... ; Cn endloop • wait ( Cond )

• { C1; C2; ... ; Cn } • wait ( Cond , Prior ) • read ( Var ) • signal ( Cond )

• write ( Var ) • send ( ProcessId, Msg ) • nl • nb_send ( ProcessId, Msg ) • tab ( K ) • receive ( ProcessId, Msg ) • nothing • id := fork

• mutexbegin • id := new Pname ( arg1, arg2, ..., argN) • mutexend • join ( id )

• lock • quit

• unlock • debug1

• insert ( id , Q ) • debug2 • insert ( id , Q, Prior ) • nodebug • id := first ( Q ) • pause

• block • exec ( Nome )

• wakeup ( id ) (Total de 40

(12)

As instruções da máquina virtual

As instruções da máquina virtual

call NomeProc [n, lista] return nothing yield hold fork join quit mutexbegin mutexend block wakeup P first Q insert P , Q is_empty Q count Q if X oprel Y goto E goto E read X write X push X pop X add sub mult div mod jump E jzer E jpos E jneg E jsub E ret P S V S entermonitor M leavemonitor M wait C wait C, Prior signal C rndzvs Entry accept Entry give_up_rndzvs send Id,Msg receive Id,Msg end proced end process end monitor end task end accept myself getId P clockTime random N nl tab X debug1 debug2 nodebug pause exec X (Total de 62 instruções)

(13)

As versões da linguagem

As versões da linguagem

Didaticamente, a linguagem oferece 6 versões:

V4

0

: processos, variáveis globais e procedimentos

V4

1

: V4

0

com operações mutexbegin/mutexend e

block/wakeup(p)

V4

2

: V4

0

com semáforos

V4

3

: V4

0

com monitores

V4

4

: processos com operações send/receive

V4

5

: tasks com threads e rendezvous.

(14)

Formas de criar processos

Formas de criar processos

Especificação de processos individuais

Especificação de array de processos

Especificação de modelo (template) de

processo

(15)

Especificação de processos (1)

Especificação de processos (1)

% Especificação individual

V4program

process p;

k: integer init 0;

while k < 10 do

{ write(1);

k:= k+1

};

process q;

k: integer init 0;

while k < 10 do

{ write(2);

k:= k+1

}

endprogram

(16)

Especificação de processos (2)

Especificação de processos (2)

% Array de processos

V4program

process p(i:= 1 to 2);

k: integer init 0;

while k < 10 do

{ write(i);

k:= k+1

}

endprogram

(17)

Especificação de processos (3)

Especificação de processos (3)

% Modelo de processo

V4program

process type p(i: integer);

k: integer init 0;

while k < 10 do

{ write(i);

k:= k+1

};

process qqnome;

{ new p(1);

new p(2)

}

endprogram

(18)

Uso de um procedimento

Uso de um procedimento

% Especificação individual e uso de procedimento

V4program

procedure imprime(n: integer);

k: integer init 0;

while k < 10 do

{ write(n);

k:= k+1

};

process p; imprime(1);

process q; imprime(2)

endprogram

(19)

Código gerado para o programa anterior

Código gerado para o programa anterior

============== TABELA DE SIMBOLOS ============== IND NOME TIPO V_INIC AGRUP INSIDE

0 imprime routine 0 n_arg(1) global

1 n integer 0 none proced(imprime) 2 k integer 0 none proced(imprime) 3 p process 9 none global

4 q process 12 none global END CÓDIGO GERADO

0 [if,#(2),<,$10,goto,2] 1 [return]

2 [write, #(1)]

3 [push, #(2)] 9 [call, imprime] 4 [push, $1] 10 [1, 1]

5 [add] 11 [end, process] 6 [pop, #(2)] 12 [call, imprime] 7 [goto, 0] 13 [1, 2]

(20)

O mesmo programa anterior

O mesmo programa anterior

% A identificação única (pid)

V4program

procedure imprime(n: integer);

k: integer init 0;

while k < 10 do

{ write(n);

k:= k+1

};

process p; imprime(myself);

process q; imprime(myself)

endprogram

(21)

Ainda o mesmo programa

Ainda o mesmo programa

% Criação de threads

% (qual o resulado da execução?)

V4program

process p;

k, id: integer init 0;

{ id:= fork();

while k < 10 do

{ write(myself);

k:= k+1

}

}

endprogram

(22)

Grafo de fluxo de processos com

Grafo de fluxo de processos com

block

block

/

/

wakeup

wakeup

(p)

(p)

V4program

process P1; { nl; write('p1');

wakeup(P3); wakeup(P4); quit };

process P2; { nl; write('p2');

wakeup(P5); quit };

process P3; { block;

nl; write('p3');

wakeup(P5); quit };

process P4; { block;

nl; write('p4');

wakeup(P5); quit };

process P5; { block; block; block;

nl; write('p5'); quit }

endprogram

p2

I

F

p1

p3

p4

p5

(23)

Grafo de fluxo de processos com

Grafo de fluxo de processos com

threads

threads

V4program

process p;

k2, k4 : integer;

{ k2:= fork;

if myself = k2 then {nl; write('p2'); quit};

nl; write('p1');

k4:= fork;

if myself = k4 then {nl; write('p4'); quit};

nl; write('p3');

join(k2);

join(k4);

nl; write('p5')

}

endprogram

p2

I

F

p1

p3

p4

p5

(24)

Variáveis semáforas

Variáveis semáforas

São variáveis especiais, sobre as quais só podem ser

aplicadas duas operações:

P

e

V

(Proberen e Verhogen).

Um semáforo é implementado por

um contador

(variável

inteira) e

uma fila de espera

.

Sendo

S

um semáforo, as operações

P

e

V

funcionam da

seguinte maneira:

P(S):

Testa o contador de S; se é zero, coloca o processo na

fila de espera (bloqueia o processo); caso contrário

decrementa o contador de 1.

V(S):

Testa a fila de S; se está vazia, incrementa o

contador de 1; caso contrário libera (desbloqueia) o

primeiro processo da fila de espera.

(25)

Grafo de fluxo de processos com semáforos

Grafo de fluxo de processos com semáforos

V4program

S3, S4, S5: semaphore initial 0;

process P1; { nl; write('p1');

V(S3); V(S4) };

process P2; { nl; write('p2');

V(S5) };

process P3; { P(S3);

nl; write('p3');

V(S5) };

process P4; { P(S4); ;

nl; write('p4');

V(S5) };

process P5; { P(S5); P(S5); P(S5);

nl; write('p5') }

endprogram

p2

I

F

p1

p3

p4

p5

(26)

O jantar dos filósofos com semáforos

O jantar dos filósofos com semáforos

V4program

garfo : array[5] of semaphore init 1;

process filosofo(i:= 1 to 5);

j, k, t: integer;

while k =< 10 do

{ if i = 1 then { P(garfo[5]); P(garfo[1])}

else {j:= i-1; P(garfo[j]); P(garfo[i])};

nl; write('filosofo '); write(i);

write(' comecou a comer');

t:=random(5); hold(t);

if i=1 then { V(garfo[5]); V(garfo[1])}

else {j := i-1 ; P(garfo[j]); P(garfo[i])};

nl; write('filosofo '); write(i);

write(' parou de comer');

k:=k+1

}

endprogram

garfo 5 filósofo 1 filósofo 5 garfo 1 garfo 4 filósofo 2 filósofo 4 garfo 2 garfo 3 filósofo 3 spaghetti

(27)

Formato de um monitor

Formato de um monitor

monitor <nome>;

| ---| ---| Declaração dos dados compartilhados pelos processos. Exemplo: | | | X, Y: integer | | | C, D: condition; | | ---| procedure P(arg1: T1,...,argP: TP);

| Declaração das variáveis locais de P; | { . . .

| wait(D);

| . . . | };

| procedure Q(arg1: T1,...,argQ: TQ); | Declaração das variáveis locais de Q; | { . . .

| signal(C);

| . . . | };

| initially {Comandos} % inicialização dos dados (opcional) end <nome>;

(28)

O jantar dos filósofos com monitores

O jantar dos filósofos com monitores

V4program

monitor garfos;

gLivre: array[5] of integer init 2; ok: array[5] of condition;

procedure pega(i:integer); j: integer; k: integer;

{ if gLivre[i] < 2 then wait(ok[i]);

j := i-1; if j=0 then j:=5; gLivre[j]:= gLivre[j]-1; k := i+1; if k=6 then k:=1; gLivre[k]:=gLivre[k]-1 };

procedure libera(i:integer); j: integer; k: integer;

{ j := i-1; if j=0 then j:=5; gLivre[j]:= gLivre[j]+1; k := i+1; if k=6 then k:=1; gLivre[k]:=gLivre[k]+1; if gLivre[j] = 2 then signal(ok[j]);

if gLivre[k] = 2 then signal(ok[k]) }

process filosofo(i:=1 to 5); k, t: integer init 0;

while k =< 10 do { garfos.pega(i);

nl; write('filos '); write(i); write(' comendo'); t:= random(5); hold(t); % come 0-4 u.t. garfos.libera(i);

nl; write('filos '); write(i); write(' pensando'); t:= random(5)+6; hold(t); % pensa 6-10 u.t. k:= k+1

}

(29)

Alocação de um recurso de N unidades

Alocação de um recurso de N unidades

V4program

monitor resource;

N: integer init 10; % 10 unidades C: condition;

procedure requisita(k: integer); { loop if k =< N then exit; wait(C) endloop; N := N-k; signal(C) };

procedure libera(k: integer); { N := N+k; signal(C) } end resource; process cliente(i:=1 to 10); { resource.requisita(i); nl; write('cliente '); write(i); resource.libera(i) } endprogram

O que acontece se, no procedimento requisita, o signal(C) é colocado logo após o wait(C)?

(30)

Formato de uma

Formato de uma

task

task

task nome is

declaração de variáveis;

declaração de entries;

declaração de procedures;

thread main is

{ C1; C2; …; Cn }

end nome

Formato do comando accept:

accept Et (arg

1

:T

1

; arg

2

:T

2

; ... ; arg

N

:T

N

) returns T

(31)

Alocação de um recurso de N unidades

Alocação de um recurso de N unidades

V4program

task resource is

entry requisita(k: integer); entry libera(k: integer); id: integer;

N: integer init 10; % recurso tem 10 unidades thread main is

{ id:= fork;

if id = myself

then loop % --- thread filha

accept requisita(k: integer) when k <= N do N:= N-k

endloop

else loop % --- thread mãe

accept libera(k: integer) do N:= N+k endloop } end resource; process cliente(i:=1 to 10); { resource.requisita(i); nl; write('cliente '); write(i); resource.libera(i) } endprogram

(32)

As operações

As operações

send

send

e

e

receive

receive

send

send

(p,

(p,

msg

msg

)

)

receive

receive

(q,

(q,

msg

msg

)

)

receive

receive

(

(

any

any

,

,

msg

msg

)

)

(33)

Comunicação via

Comunicação via

fork

fork

,

,

join

join

e

e

quit

quit

id:=

id:=

fork

fork

quit

quit

join

join

(id)

(id)

quit

quit

(Valor)

(Valor)

var:=

var:=

join

join

(id)

(id)

(34)

As facilidades de depuração

As facilidades de depuração

debug1

debug1

debug2

debug2

nodebug

nodebug

exec

exec

(Nome)

(Nome)

pause

pause

(35)

Conclusão (1)

Conclusão (1)

Instalação do sistema:

Criar a pasta (diretório) “Vale4”

Fazer download do SWI-Prolog (programa de instalação) a

partir do site:

http://www.swi-prolog.org/

3.

Instalar o SWI-Prolog na pasta “Vale4”

(a instalação vai criar o diretório “pl”)

4.

Copiar os arquivos V4compiler, V4_1 e V4_2 e

programas exemplos para a pasta “Vale4”.

(36)

Conclusão (2)

Conclusão (2)

O sistema está operacional.

O sistema está operacional.

Sua instalação é muito simples.

Sua instalação é muito simples.

V4 é uma ferramenta para treinamento

V4 é uma ferramenta para treinamento

(ensino/aprendizagem).

(ensino/aprendizagem).

Não é linguagem para produção de software (não há

Não é linguagem para produção de software (não há

preocupação com geração de código otimizado, tampouco

preocupação com geração de código otimizado, tampouco

com eficiência de execução).

com eficiência de execução).

A linguagem é usada para ilustrar o livro “Programação

A linguagem é usada para ilustrar o livro “Programação

Concorrente e Sistemas Operacionais” que será lançado

Concorrente e Sistemas Operacionais” que será lançado

em breve.

(37)

Barbeiro dorminhoco (

Barbeiro dorminhoco (

task

task

e

e

threads

threads

)

)

V4program

task barbershop is

k, t, id1, id2: integer; empty_chair: boolean; #chairs: integer initial 3; entry client_in(id: integer);

procedure avail_chair() returns boolean; { mutexbegin;

if #chairs > 0 then { #chairs:= #chairs-1; avail_chair:= true } else avail_chair:= false;

mutexend };

thread main is { id1:= fork;

if id1 = myself

then loop % loop da thread barbeiro

accept client_in(id: integer) do % dorme se não há cliente { nl; write('client '); write(id);

write(' at time '); write(clockTime); hold(2); #chairs:= #chairs+1 }

(38)

Barbeiro dorminhoco (continuação)

Barbeiro dorminhoco (continuação)

loop % thread main gera 20 clientes id2:= fork;

if id2 = myself then { empty_chair:= avail_chair();

if empty_chair then client_in(id2); quit };

t:= random(6); hold(t); % espera um tempo entre 0 e 5 u.t. (média 2.5) k:= k+1; exit when k=20 endloop } end barbershop end program

(39)

Busca do elemento máximo de um vetor por divisão e conquista

Busca do elemento máximo de um vetor por divisão e conquista

V4program task xmax is

vet: array[10] of integer;

Imax: integer init 0; % Índice do maior elemento do vetor procedure getmax(i:integer; j:integer) returns integer;

dif, m, m1, id1, id2, max1, max2: integer; { dif:=j-i;

if dif=0 then getmax:=i

else if dif=1 then if vet[i]>vet[j] then getmax:=i else getmax:=j else { m:=(i+j)/2; m1:=m+1;

id1:=fork;

if id1=myself then {max1:=getmax(i,m); quit}; id2:=fork;

if id2=myself then {max2:=getmax(m1,j);quit}; join(id1); join(id2);

if vet[max1] > vet[max2] then getmax:=max1 else getmax:=max2

} };

thread main is

{ vet[1]:=1; vet[2]:=10; vet[3]:=3; vet[4]:=100; vet[5]:=2; Imax:=getmax(1,5); nl; write('Vobtido = '); write(vet[Imax]) }

(40)

Monitor para o problema dos

Monitor para o problema dos

readers

readers

&

&

writers

writers

monitor ReadersAndWriters; #readers: integer initial 0;

activeWriter: boolean initial false; okToRead, okToWrite: condition; procedure startRead();

{ if activeWriter or ¬empty(okToWrite) then wait(okToRead); #readers:=#readers+1; signal(okToRead)

};

procedure endRead();

{ #readers:=#readers-1; if #readers=0 then signal(okToWrite) };

procedure startWrite();

{ if #readers>0 or activeWriter then wait(okToWrite); activeWriter:=true

};

procedure endWrite(); { activeWriter:=false;

if ¬empty(okToRead) then signal(okToRead) else signal(okToWrite)

(41)

Produtores

Produtores

-

-

consumidores com semáforos

consumidores com semáforos

V4program

buffer: array[2] of integer init 0;

cheios: semaphore init 0;

vazios: semaphore init 2;

mutex : semaphore init 1;

in,out: integer init 1;

process produtor(i:=0 to 1);

nextpar: integer init 0;

nextimpar: integer init 1;

while nextimpar < 20 & nextpar < 20 do

{ P(vazios) ;

P(mutex);

if i = 0 then { nextpar:= nextpar + 2;

buffer[in]:= nextpar }

else { nextimpar:= nextimpar + 2;

buffer[in]:= nextimpar };

in:=(in mod 2)+1;

V(mutex);

V(cheios)

};

process consumidor(i:=1 to 2);

msg: integer;

do forever

{ P(cheios);

P(mutex);

msg:= buffer[out];

out:=(out mod 2)+1;

V(mutex);

V(vazios);

nl; if i = 2 then tab(10);

write(msg)

}

endprogram

Referências

Documentos relacionados

Para identificar quais treinamentos serão necessários para cada trabalhador ou equipe dentro de uma organização desenvolver um programa eficaz de T&amp;D, pode-se buscar

- Se o estagiário, ou alguém com contacto direto, tiver sintomas sugestivos de infeção respiratória (febre, tosse, expetoração e/ou falta de ar) NÃO DEVE frequentar

Este resultado ajuda a explicar o fenômeno de running-in da curva do coeficiente de atrito apresentado na Seção 4.4. No início do deslizamento o contato é primariamente entre os

Almanya'da olduğu gibi, burada da bu terimin hiçbir ayrım gütmeden, modern eğilimleri simgeleyen tüm sanatçılar için geçerli olduğu anlaşılıyor.. SSCB'de ilk halk

Exercer o controle e a fiscalização das contas públicas, coordenar, fiscalizar e avaliar as atividades de controle interno da Administração Pública Municipal, devendo zelar

Também se verificou a existência de fatores que estão inibindo a evolução do cluster do Vale do Cariri, onde se observa a baixa preocupação pelas vendas ao mercado

No sentido de reverter tal situação, a realização deste trabalho elaborado na disciplina de Prática enquanto Componente Curricular V (PeCC V), buscou proporcionar as

Logo, a capacitação de professores na educação de surdos e na Língua Brasileira de Sinais é essencial, considerando que o reconhecimento da multiculturalidade na