260 likes | 376 Views
Programação Concorrente. Ambientes Operacionais Prof. Simão Sirineo Toscani. Programa Seqüencial x Programa Concorrente.
E N D
Programação Concorrente Ambientes Operacionais Prof. Simão Sirineo Toscani
Programa Seqüencial x Programa Concorrente • Um programa seqüencial possui um único fluxo de controle (fluxo de execução, linha de execução, thread). Isso permite que o programador realize uma "execução imaginária" de seu programa apontando com o dedo, a cada instante, o comando que está sendo executado. • Um programa concorrente possui vários fluxos de execução. Para o programador realizar agora uma "execução imaginária", ele vai necessitar de vários dedos, um para cada fluxo de controle. • Execução lógicamente paralela e execução fisicamente paralela.
Programa Seqüencial x Programa Concorrente • A programação concorrente é mais complexa. Um programa concorrente pode apresentar todos os tipos de erros que aparecem nos programas seqüenciais e, adicionalmente, os erros associados com as interações entre os processos. • Muitos erros dependem do exato instante de tempo em que o escalonador do sistema operacional realiza um chaveamento de contexto. Isso torna muitos erros difíceis de reproduzir e de identificar.
Aplicações da programação concorrente • A programação concorrente é natural para vários tipos de aplicações, principalmente para aquelas que apresentam paralelismo implícito • Aplicações com paralelismo implícito: aquelas para as quais pode-se distinguir facilmente funções para serem realizadas em paralelo
Especificação do paralelismo • Primitivas forkjoin e quit • Primitiva fork no sistema Unix: id = fork() if id = 0 then { processamento do filho } else { processamento do pai }
Especificação do paralelismo • Primitiva fork no sistema Vale4: (no sistema Vale4, o fork cria uma thread) id = fork() if id = myNumber then { processamento da filha } else { processamento da mãe }
Especificação do paralelismo • Primitivas join(id) e quit • Diferença entre thread e processo: • Basicamente, está no espaço de endereçamento
Especificação do paralelismoUm exemplo V4program process p1; f1: integer; /* identifica filha 1*/ f2: integer; /* identifica filha 2*/ { write('Alo da mae'); nl; f1:= fork(); /* Cria filha 1 */ if f1 = myNumber then { write('Alo da filha 1'); nl; quit}; f2:= fork(); /* Cria filha 2 */ if f2 = myNumber then { write('Alo da filha 2'); nl; quit}; join(f1); write('Filha 1 morreu'); nl; join(f2); write('Filha 2 morreu'); nl } end program
Especificação do paralelismoCriação estática de processos (possibilidade 1) 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 } end program
Especificação do paralelismoCriação estática de processos (possibilidade 2) V4program process P (i := 1 to 2); % array de processos k: integer init 0; while k < 10 do { write(i); k:=k+1 } endprogram
Especificação do paralelismoCriação dinâmica 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
Especificação do paralelismoTorre de Hanoi V4program process type Hanoi(n, a, b, c: integer); id, m: integer; if n = 1 then { nl; write(a); write(' --> '); write(b) } else { m:= n-1; id:= new Hanoi(m, a, c, b); join(id); nl; write(a); write(' --> '); write(b); id:= new Hanoi(m, c, b, a); join(id) }; process P; new Hanoi(3, 1, 2, 3) endprogram
Especificação do paralelismoCompartilhamento 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
Especificação do paralelismoCompartilhamento de uma variável V4program S : integer init 0; process p1; 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
O problema da exclusão mútua Comando em linguagem de alto nível: S:= S+1; Código gerado pelo compilador: push S % coloca o valor de S na pilha push $1 % coloca a constante 1 na pilha add % soma os dois últimos valores colocados na pilha pop S % guarda o resultado em S
Mecanismos de sincronização • Operações lock e unlock • Operações block e wakeup(P) • Semáforos • Monitores • Tasks • Operações send e receive
Mecanismos de sincronizaçãoSemáforos Semáforos são variáveis especiais que admitem apenas duas operações, denominadas P e V. Sendo S é uma variável semáfora, as operações P e V têm a seguinte semântica: • P(S) : espera até S ser maior que 0 e então subtrai 1 de S; • V(S) : incrementa S de 1.
Problemas clássicos • Produtor - consumidor • Jantar dos filósofos • Barbeiro dorminhoco • Leitores e escritores • Fumantes • Etc.
Problemas clássicosJantar dos filósofos V4program garfo: array[5] of semaphore init 1; % array global procedure getForks(i: integer); j: integer; { j := i-1 ; % j é o garfo da esquerda if j = 0 then { P(garfo[1]); P(garfo[5]) } else { P(garfo[j]); P(garfo[i]) } }; procedure putForks(i: integer); j: integer; { j := i-1 ; % j é o garfo da esquerda if j = 0 then { V(garfo[1]); V(garfo[5]) } else { V(garfo[j]); V(garfo[i]) } }; process filosofo (i:= 1 to 5); k: integer init 10; while k > 0 do { getForks(i); nl; write(‘filosofo ’); write(i); write(‘ comecou a comer’); putForks(i); nl; write(‘filosofo ’); write(i); write(‘ parou de comer’); k:=k-1 } endprogram
Problemas clássicosLeitores e escritores Variáveis globais: mutex, w : semaphore initial 1; nr : integer initial 0; Processo leitor: . . . P(mutex); Processo escritor: nr:=nr+1; . . . if nr=1 then P(w); . . . V(mutex); P(w); READ WRITE P(mutex); V(w); nr:=nr-1; . . . if nr=0 then V(w); . . . V(mutex); . . .