SO-03 Comunicação e Sincronização de Processos
Upcoming SlideShare
Loading in...5
×
 

SO-03 Comunicação e Sincronização de Processos

on

  • 14,364 views

Comunicação e Sincronização de Processos. Problemas Clássicos de Sincronização de Processos (Sistemas Operacionais)

Comunicação e Sincronização de Processos. Problemas Clássicos de Sincronização de Processos (Sistemas Operacionais)

Statistics

Views

Total Views
14,364
Slideshare-icon Views on SlideShare
14,298
Embed Views
66

Actions

Likes
5
Downloads
550
Comments
6

2 Embeds 66

http://www.slideshare.net 65
http://www.linkedin.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

16 of 6 Post a comment

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • bato palmas ae...
    Are you sure you want to
    Your message goes here
    Processing…
  • ja pela divulgação é um bom resultado
    Are you sure you want to
    Your message goes here
    Processing…
  • very good
    Are you sure you want to
    Your message goes here
    Processing…
  • muito boa...
    Are you sure you want to
    Your message goes here
    Processing…
  • muito bom!
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    SO-03 Comunicação e Sincronização de Processos SO-03 Comunicação e Sincronização de Processos Presentation Transcript

    • Processos Comunicação e Sincronização
    •   Processos Concorrentes   Comunicação Interprocessos   O Problema da Seção Crítica   Sincronização por Hardware e por Software   Semáforos   Problemas Clássicos de Sincronização Eduardo Nicola F. Zagari 2 Comunicação e Sincronização
    •   Processos que executam ao mesmo tempo podem existir de maneira independente um dos outros ou podem requerer sincronização ocasional ou cooperação.   Processos Independentes versus Processos Cooperantes   Independentes: não afetam nem são afetados pela execução de um outro processo   Cooperantes: podem afetar ou serem afetados pela execução de outros processos   Vantagens da cooperação:   compartilhamento de informação   aumento da velocidade de computação   modularidade   conveniência Eduardo Nicola F. Zagari 3 Comunicação e Sincronização
    •   Paradigma de processos cooperantes:   producer produz informação que é consumida pelo consumer  Buffer sem limite  Buffer limitado Sincronização Processo Processo Produtor Consumidor dados dados buffer tamanho ilimitado x limitado Eduardo Nicola F. Zagari 4 Comunicação e Sincronização
    • public interface Buffer { // producers call this method public abstract void insert(Object item); // consumers call this method public abstract Object remove(); } Eduardo Nicola F. Zagari 5 Comunicação e Sincronização
    • import java.util.*; public class BoundedBuffer implements Buffer { private static final int BUFFER SIZE = 5; private int count; // number of items in the buffer private int in; // points to the next free position private int out; // points to the next full position private Object[] buffer; public BoundedBuffer() { // buffer is initially empty count = 0; in = 0; out = 0; buffer = new Object[BUFFER SIZE]; } // producers calls this method public void insert(Object item) { // Slide 7 } // consumers calls this method public Object remove() { Eduardo Nicola F. Zagari // Slide 8 6 Comunicação e Sincronização }
    • public void insert(Object item) { while (count == BUFFER SIZE) ; // do nothing -- no free buffers // add an item to the buffer ++count; buffer[in] = item; in = (in + 1) % BUFFER SIZE; } Eduardo Nicola F. Zagari 7 Comunicação e Sincronização
    • public Object remove() { Object item; while (count == 0) ; // do nothing -- nothing to consume // remove an item from the buffer --count; item = buffer[out]; out = (out + 1) % BUFFER SIZE; return item; } Eduardo Nicola F. Zagari 8 Comunicação e Sincronização
    •   Mecanismo do SO que permite que processos se comuniquem e sincronizem suas ações   Sistema de Mensagens – processos se comunicam entre si sem a necessidade de compartilhar variáveis   IPC fornece duas operações:   send(message) – mensagem de tamanho fixo ou variável   receive(message)   Se P e Q desejam se comunicar, eles precisam:   Estabelecer um canal de comunicação entre eles   Trocar mensagens via send/receive   Implementação do canal de comunicação:   físico (p.ex.: memória compartilhada)   lógico (p.ex.: propriedades lógicas) Eduardo Nicola F. Zagari 9 Comunicação e Sincronização
    •   Como a ligação é estabelecida?   Pode ser associada a mais de 2 processos?   Quantas ligações podem existir entre 2 processos?   Qual a capacidade?   Tamanho da mensagem fixo ou variável?   Unidirecional ou bidirecional? Eduardo Nicola F. Zagari 10 Comunicação e Sincronização
    • Comunicação direta x indireta mailbox send(P, mensagem) send(A, mensagem) receive(Q, mensagem) receive(A, mensagem)   ligação automática   ligação entre processos que   ligação entre 2 processos compartilham A   só existe uma ligação   ligação entre 2 ou mais processos   uni ou bidirecional   podem existir várias ligações   desvantagem: se mudar o ID do   uni ou bidirecional processo?   Processos têm que compartilhar o mailbox (ID único) Eduardo Nicola F. Zagari 11 Comunicação e Sincronização
    •   Troca de Mensagens pode ser bloqueante ou não-bloqueante   Bloqueante é considerada síncrona   send bloqueante – quem envia espera até que uma mensagem seja recebida   receive bloqueante – quem recebe espera até que uma mensagem esteja disponível   Não-bloqueante é considerada assíncrona   send não-bloqueante – o transmissor envia a mensagem e continua   receive não-bloqueante – o receptor recebe uma mensagem válida ou um null Eduardo Nicola F. Zagari 12 Comunicação e Sincronização
    •   Filas de mensagens implementam uma das três capacidades: 1.  Zero – 0 mensagens
 não pode haver mensagem esperando, quem envia deve esperar até que a mensagem seja recebida (sincronizada) 2.  Limitada – número finito de n mensagens
 se está cheio, quem envia deve esperar 5.  Ilimitada – tamanho infinito 
 quem envia nunca espera Eduardo Nicola F. Zagari 13 Comunicação e Sincronização
    •   Acesso concorrente a dados compartilhados podem resultar em inconsistência dos mesmos   Manter a consistência dos dados requer mecanismos para assegurar a execução ordenada dos processos cooperantes   Race condition : situação em que dois ou mais processos querem partilhar um recurso (escrever e ler dados compartilhados) e o resultado final depende de quem executou quando (ordem de escalonamento)   Processos concorrentes necessitam de mecanismos de sincronização para evitar que outro processo tenha acesso a uma variável comum, quando esta está sendo modificada por um processo Eduardo Nicola F. Zagari 14 Comunicação e Sincronização
    •   solução de Shared-memory para o problema do buffer limitado A tem uma condição de corrida na classe de dados count. Produtor Consumidor while (1) { while (1) { while (count ==BUFFER_SIZE) while (count == 0) ; // não faz nada ; // não faz nada // produz um item e o coloca nextConsumed = buffer[out]; em nextProduced out = (out + 1) % BUFFER_SIZE; buffer[in] = nextProduced; count--; in = (in + 1) % BUFFER_SIZE; // consome o item em nextConsumed count++; } } Eduardo Nicola F. Zagari 15 Comunicação e Sincronização
    •   count++ poderia ser implementado como
 register1 = count
 register1 = register1 + 1
 count = register1   count– poderia ser implementado como
 register2 = count
 register2 = register2 - 1
 count = register2   Considere esta intercalação de execução: S0: produtor executa register1 = count {register1 = 5}
 S1: produtor executa register1 = register1 + 1 {register1 = 6} 
 S2: consumidor executa register2 = count {register2 = 5} 
 S3: consumidor executa register2 = register2 - 1 {register2 = 4} 
 S4: produtor executa count = register1 {count = 6 } 
 S5: consumidor executa count = register2 {count = 4} Eduardo Nicola F. Zagari 16 Comunicação e Sincronização
    •   Como evitar condições de corrida?   Evitar que os processos leiam e escrevam dados compartilhados ao mesmo tempo   Exclusão Mútua: se um processo estiver usando uma variável ou arquivo, o outro processo está excluído do uso   Isto é, garantia de acesso exclusivo a um recurso   Parte do tempo o processo executa computação que não leva a condições de corrida  a parte do programa em que memória compartilhada é acessada é chamada de Região Crítica ou Seção Crítica Eduardo Nicola F. Zagari 17 Comunicação e Sincronização
    • 1.  Exclusão Mútua – Se o processo Pi está executando dentro da sua seção crítica, então nenhum outro processo pode estar executando em sua seção crítica correspondente   Dois processos não podem estar simultaneamente dentro de suas regiões críticas correpondentes 3.  Progresso – Se nenhum processo está executando dentro de sua seção crítica e existem alguns processos que desejam adentrar suas seções críticas, então a seleção do próximo processo que irá entrar em sua seção crítica não pode ser adiada   Nenhum processo que esteja rodando fora de sua seção crítica pode bloquear a execução de outro processo 5.  Espera Limitada - Nenhum processo pode ser obrigado a esperar indefinidamente para entrar em sua região crítica   Nenhuma suposição pode ser feita com relação à velocidade de execução dos processos ou ao número de processadores disponíveis no sistema Eduardo Nicola F. Zagari 18 Comunicação e Sincronização
    •   Mecanismos de Hardware:   Inibição de Interrupções   Instrução TSL (Test and Set Lock)   Mecanismos de Software:   Com Espera Ocupada:  Variáveis de Travamento (Lock Variables)  Alternância Estrita  Solução de Peterson   Sem Espera Ocupada:   Dormir e Acordar (Sleep and Wakeup)   Semáforos   Contadores de Eventos   Monitores   Troca de Mensagens Eduardo Nicola F. Zagari 19 Comunicação e Sincronização
    •   Solução mais simples   Desabilitam-se todas as interrupções após se entrar na região crítica  ao sair, reabilitam-nas   Se as interrupções não ocorrem, o processo não pode sofrer preempção   Problema 1: ... e se o processo não reabilitar as interrupções?   Problema 2: se o sistema tem 2 CPUs e somente uma tem as interrupções inibidas, a outra pode acessar a memória compartilhada   Por outro lado, é muito conveniente que o kernel possa desabilitar as interrupções para atualizar variáveis ou listas   Conclusão: solução adequada para o kernel, mas não para processos de usuário Eduardo Nicola F. Zagari 20 Comunicação e Sincronização
    •   Instrução especial que permite ler uma variável, armazenar seu conteúdo em uma outra área e atribuir um novo valor a esta variável (hardware)   É uma instrução indivisível: executada sem interrupção   Variável compartilhada flag: quando flag = 0, qualquer processo pode fazê-la igual a 1 (instrução TSL) Eduardo Nicola F. Zagari 21 Comunicação e Sincronização
    • enter_region: tsl register, flag | copia flag p/ | registrador e faz flag = 1 cmp register, #0 | o flag é zero? jnz enter_region | se não,lock e setado;loop ret | retorna, entrou na R.C. leave_region: mov flag, #0 | guarda um 0 em flag ret | retorna a quem chamou Eduardo Nicola F. Zagari 22 Comunicação e Sincronização
    •   Define-se uma única variável compartilhada, inicialmente com valor zero   Se um processo deseja entrar na região crítica, ele testa a variável. Se ela for 1 (recurso liberado), ela é feita 0 (recurso trancado) e o processo entra. Caso contrário, o processo aguarda até que o valor da variável seja 1 (um) Eduardo Nicola F. Zagari 23 Comunicação e Sincronização
    • x = 0, recurso trancado x = 1, recurso liberado while (x == 0) do /* nada */; Entrada x = 0; Entrada ... Região Crítica x = 1; Saída   Problema: Este mecanismo apresenta a falha de que a alteração de valor para “trancado”ʼ, após o teste, permite que dois processos executem a Região Crítica (RC) ao mesmo tempo   O teste e a alteração necessitam ser feitos de forma indivisível (atômica) Eduardo Nicola F. Zagari 24 Comunicação e Sincronização
    • Processo A Processo B while (TRUE) { while (TRUE) { while (turn != 0); while (turn != 1); Reg_Crítica(); Reg_Crítica(); turn = 1; turn = 0; Reg_Não_Crítica(); Reg_Não_Crítica(); } }   Inicialmente a variável turn é feita igual a 0 (zero)   Assim, o Processo A consegue entrar na região crítica   Enquanto isto, o Processo B ficará continuamente testando a variável (Espera Ocupada) Eduardo Nicola F. Zagari 25 Comunicação e Sincronização
    •   Problema 1: o fato do Processo B ficar fazendo “Espera Ocupada” deve ser evitado, pois consome tempo de CPU   Problema 2: não é uma boa solução quando um processo é muito mais lento que o outro   Problema 3: viola a condição de que um processo que não esteja em sua região crítica não bloqueie outro Eduardo Nicola F. Zagari 26 Comunicação e Sincronização
    •   Antes de entrar na Região Crítica (RC), cada processo chama enter_region com seu no (0 ou 1) como parâmetro. Ao sair, leave_region #include “prototypes.h” #define FALSE 0 #define TRUE 1 #define N 2 /* no de processos */ int turn; /* de quem é a vez */ int interested[N]; /* todos valores inici- */ /* almente 0 (FALSE) */ Eduardo Nicola F. Zagari 27 Comunicação e Sincronização
    • void enter_region (int process) { /* process = quem está entrando (0 ou 1) */ int other; /* no do outro processo */ other = 1 - process; /* o outro processo */ interested[process] = TRUE; /* mostra interesse */ turn = process; /* define flag */ while (turn==process && interested[other]==TRUE); } void leave_region (int process) { /* process = quem está saindo */ interested[process] = FALSE; /* indica saída RC */ } Eduardo Nicola F. Zagari 28 Comunicação e Sincronização
    •   Duas tarefas, T0 e T1 (Ti e Tj)   Três “soluções” são apresentadas. Todas elas implementam a interface MutualExclusion :
 public interface MutualExclusion
 {
 public static final int TURN_0 = 0;
 public static final int TURN_1 = 1;
 public abstract void enteringCriticalSection(int turn);
 public asbtract void leavingCriticalSection(int turn);
 } Eduardo Nicola F. Zagari 29 Comunicação e Sincronização
    • Usado para criar duas threads e testar cada algoritmo public class AlgorithmFactory { public static void main(String args[]) { MutualExclusion alg = new Algorithm_1(); Thread first = new Thread( new Worker("Worker 0", 0, alg)); Thread second = new Thread(new Worker("Worker 1", 1, alg));
 first.start(); second.start(); } } Eduardo Nicola F. Zagari 30 Comunicação e Sincronização
    • public class Worker implements Runnable {
 private String name; private int id; private MutualExclusion mutex; public Worker(String name, int id, MutualExclusion mutex) { this.name = name; this.id = id; this.mutex = mutex; } public void run() { while (true) { mutex.enteringCriticalSection(id); MutualExclusionUtilities.criticalSection(name); mutex.leavingCriticalSection(id); MutualExclusionUtilities.nonCriticalSection(name); } } } Eduardo Nicola F. Zagari 31 Comunicação e Sincronização
    •   Threads compartilham uma variável inteira comum (turn)   Se turn==i, thread i é permitda a executar   Não satisfaz o requisito “Progresso”   Por quê? Eduardo Nicola F. Zagari 32 Comunicação e Sincronização
    • public class Algorithm_1 implements MutualExclusion { private volatile int turn;
 public Algorithm_1() { turn = TURN_0; } public void enteringCriticalSection(int t) { while (turn != t) Thread.yield(); } public void leavingCriticalSection(int t) { turn = 1 - t; } } Eduardo Nicola F. Zagari 33 Comunicação e Sincronização
    •   Adicionar mais informação de estado   Flags booleanas para indicar o interesse das threads em entrar na seção crítica   O requisito “Progresso” ainda não é satisfeito   Por quê? Eduardo Nicola F. Zagari 34 Comunicação e Sincronização
    • public class Algorithm_2 implements MutualExclusion { private volatile boolean flag0, flag1; public Algorithm_2() { flag0 = false; flag1 = false; } public void enteringCriticalSection(int t) { if (t == 0) { flag0 = true; while(flag1 == true) Thread.yield(); } else { flag1 = true; while (flag0 == true) Thread.yield(); } } // Continued On Next Slide Eduardo Nicola F. Zagari 35 Comunicação e Sincronização
    • public void leavingCriticalSection(int t) { if (t == 0) flag0 = false; else flag1 = false; } } Eduardo Nicola F. Zagari 36 Comunicação e Sincronização
    •   Combina as idéias de 1 e 2   Ele satisfaz os requisitos da solução do problema da seção crítica? Eduardo Nicola F. Zagari 37 Comunicação e Sincronização
    • public class Algorithm_3 implements MutualExclusion { private volatile boolean flag0; private volatile boolean flag1; private volatile int turn; public Algorithm_3() { flag0 = false; flag1 = false; turn = TURN_0; } // Continued on Next Slide Eduardo Nicola F. Zagari 38 Comunicação e Sincronização
    • public void enteringCriticalSection(int t) { int other = 1 - t; turn = other; if (t == 0) { flag0 = true; while(flag1 == true && turn == other) Thread.yield(); } else { flag1 = true; while (flag0 == true && turn == other) Thread.yield(); } } // Continued on Next Slide Eduardo Nicola F. Zagari 39 Comunicação e Sincronização
    • public void leavingCriticalSection(int t) { if (t == 0) flag0 = false; else flag1 = false; } } Eduardo Nicola F. Zagari 40 Comunicação e Sincronização
    •   Problema da Solução de Peterson e da Instrução TSL: o processo que não consegue acesso à R.C. permanece em “espera ocupada” (busy waiting):   gasta tempo de processador inutilmente   pode provocar o Problema da Inversão de Prioridade: Dois processos A (alta prioridade) e B (baixa prioridade) »  B entra na Região Crítica; »  A vai para estado de pronto; »  A passa para estado de execução; »  A fica testando indefinidamente.   Chamadas de sistema: SLEEP e WAKEUP Eduardo Nicola F. Zagari 41 Comunicação e Sincronização
    •   Dois processos compartilham um buffer de tamanho fixo. Um dos processos, o produtor, coloca informação no buffer, e o outro, o consumidor, retira informação do buffer.   Se o buffer estiver cheio, o produtor dorme e é acordado quando o consumidor remover um item   Se o buffer estiver vazio, o consumidor dorme até que seja produzido e armazenado algum item Eduardo Nicola F. Zagari 42 Comunicação e Sincronização
    • #define N 100 /* no máximo de ítens */ int count = 0; /* no de ítens no buffer */ Produtor Consumidor void producer (void) { void consumer(void) { int item; int item; while (TRUE) { while (TRUE) { produce_item(&item); if (count==0) sleep(); if (count==N) sleep(); remove_item(&item); enter_item(item); count -= 1; count += 1; if (count==N-1) if (count==1) wakeup(producer); wakeup(consumer); consume_item(item); } } } } Eduardo Nicola F. Zagari 43 Comunicação e Sincronização
    •   Problema:   Se o buffer estiver vazio e o consumidor sofrer preempção antes de dormir  o produtor produz e envia um wakeup para o consumidor que ainda não está dormindo  o sinal se perde e o consumidor dormirá para sempre... Eduardo Nicola F. Zagari 44 Comunicação e Sincronização
    •   Mecanismo de sincronização que não requer espera ocupada   Dijkstra propôs usar uma variável inteira para contar o no de WAKEUPs para uso futuro   Menos complicado   Esta variável, denominada semáforo, pode ter valor 0 (nenhum WAKEUP pendente) ou um valor inteiro positivo   Apenas duas operações são definidas sobre estas variáveis: as operações P (Down) e V (Up) Eduardo Nicola F. Zagari 45 Comunicação e Sincronização
    • P(s) (Down) - checa o valor do semáforo. Se o valor é maior que 0 (zero), decrementa e continua. Se for igual a 0, o processo é posto para dormir  Ação atômica: é garantido que, uma vez iniciada a operação, nenhum outro processo tem acesso ao semáforo (essencial para resolver problemas de sincronização e evitar condições de corrida) P(s) equivale a: Se s > 0 então s := s - 1 senão bloqueia o processo até s > 0 (= wait(s)) V(s) (Up) - se um ou mais processos estão dormindo no semáforo, um deles é escolhido aleatoriamente pelo SO e continua sua operação Down (o valor zero continua). Se não há ninguém “dormindo” no semáforo, incrementa o valor dele  Operação também é indivisível V(s) equivale a: Verifica se existe uma lista com processos bloqueados por causa de s, se existe escolhe um e o “acorda”, deixando-o pronto para seguir sua execução de P(s) (= signal(s)) senão s := s + 1 Eduardo Nicola F. Zagari 46 Comunicação e Sincronização
    •   Semáforo Contador – valor inteiro positivo pode variar sem limites   Semáforo Binário – valor inteiro só pode variar entre 0 e 1;   Também conhecido como mutex locks   Para fornecer exclusão mútua: Semaphore S; // initialized to 1 P(S); criticalSection(); V(S); Eduardo Nicola F. Zagari 47 Comunicação e Sincronização
    • #define N 100 /* no máximo de ítens */ typedef int semaphore; semaphore mutex = 1; /* controla acesso à RC */ semaphore empty = N; /* conta slots vazios */ semaphore full = 0; /* conta slots ocupados */ void producer (void) { void consumer(void) { int item; int item; while (TRUE) { while (TRUE) { produce_item(&item); P(&full); P(&empty); P(&mutex); P(&mutex); remove_item(&item); enter_item(item); V(&mutex); V(&mutex); V(&empty); V(&full); consume_item(item); } } } } Eduardo Nicola F. Zagari 48 Comunicação e Sincronização
    • public class Worker implements Runnable { private Semaphore sem; private String name; public Worker(Semaphore sem, String name) { this.sem = sem; this.name = name; } public void run() { while (true) { sem.acquire(); MutualExclusionUtilities.criticalSection(name); sem.release(); MutualExclusionUtilities.nonCriticalSection(name); } } } Eduardo Nicola F. Zagari 49 Comunicação e Sincronização
    • public class SemaphoreFactory { public static void main(String args[]) { Semaphore sem = new Semaphore(1); Thread[] bees = new Thread[5]; for (int i = 0; i < 5; i++) bees[i] = new Thread(new Worker (sem, "Worker " + (new Integer(i)).toString() )); for (int i = 0; i < 5; i++) bees[i].start(); } } Eduardo Nicola F. Zagari 50 Comunicação e Sincronização
    •   Deadlock – dois ou mais processos ficam esperando indefinidamente por um evento que pode ser causado apenas por um dos processos bloqueados   Sejam S e Q dois semáforos inicializados com 1 P0 P1 P(S); P(Q); P(Q); P(S); . . . . . . V(S); V(Q); V(Q); V(S);   Starvation – bloqueio indefinido. Um processo pode nunca ser removido da fila de semáforos na qual ele está bloqueado. Eduardo Nicola F. Zagari 51 Comunicação e Sincronização
    •   Problema do Buffer Limitado   Problema dos Leitores e Escritores   Problema do Jantar dos Filósofos Eduardo Nicola F. Zagari 52 Comunicação e Sincronização
    • public class BoundedBuffer implements Buffer { private static final int BUFFER SIZE = 5; private Object[] buffer; private int in, out; private Semaphore mutex; private Semaphore empty; private Semaphore full; // Continued on next Slide Eduardo Nicola F. Zagari 53 Comunicação e Sincronização
    • public BoundedBuffer() { // buffer is initially empty in = 0; out = 0; buffer = new Object[BUFFER SIZE]; mutex = new Semaphore(1); empty = new Semaphore(BUFFER SIZE); full = new Semaphore(0); } public void insert(Object item) { /* next slides */ } public Object remove() { /* next slides */ } } Eduardo Nicola F. Zagari 54 Comunicação e Sincronização
    • public void insert(Object item) { empty.acquire(); mutex.acquire(); // add an item to the buffer buffer[in] = item; in = (in + 1) % BUFFER SIZE; mutex.release(); full.release(); } Eduardo Nicola F. Zagari 55 Comunicação e Sincronização
    • public Object remove() { full.acquire(); mutex.acquire(); // remove an item from the buffer Object item = buffer[out]; out = (out + 1) % BUFFER SIZE; mutex.release(); empty.release(); return item; } Eduardo Nicola F. Zagari 56 Comunicação e Sincronização
    • import java.util.Date; public class Producer implements Runnable { private Buffer buffer; public Producer(Buffer buffer) { this.buffer = buffer; } public void run() { Date message; while (true) { // nap for awhile SleepUtilities.nap(); // produce an item & enter it into the buffer message = new Date(); buffer.insert(message); } } } Eduardo Nicola F. Zagari 57 Comunicação e Sincronização
    • import java.util.Date; public class Consumer implements Runnable { private Buffer buffer; public Consumer(Buffer buffer) { this.buffer = buffer; } public void run() { Date message; while (true) { // nap for awhile SleepUtilities.nap(); // consume an item from the buffer message = (Date)buffer.remove(); } } } Eduardo Nicola F. Zagari 58 Comunicação e Sincronização
    • public class Factory { public static void main(String args[]) { Buffer buffer = new BoundedBuffer(); // now create the producer and consumer threads Thread producer = new Thread(new Producer(buffer)); Thread consumer = new Thread(new Consumer(buffer)); producer.start(); consumer.start(); } } Eduardo Nicola F. Zagari 59 Comunicação e Sincronização
    •   Acesso a uma base de dados   É aceitável que haja mais de um processo lendo a base de dados ao mesmo tempo, mas...   ... se um processo estiver escrevendo na base, nenhum outro processo, nem mesmo os leitores, podem ter acesso a ela, enquanto o escritor não tiver terminado Eduardo Nicola F. Zagari 60 Comunicação e Sincronização
    • void reader (void) { while (TRUE) { Program Solução; P(&mutex); typedef int semaphore; rc++; semaphore mutex = 1; semaphore db = 1; if (rc == 1) int rc = 0; P(&db); void writer (void) { V(&mutex); while (TRUE) { read_data_base(); think_up_data(); P(&mutex); P(&db); rc--; write_data_base(); if (rc == 0) V(&db); V(&db); } V(&mutex); } use_data_read(); } Eduardo Nicola F. Zagari 61 } Comunicação e Sincronização
    • public class Reader implements Runnable { private RWLock db; public Reader(RWLock db) { this.db = db; } public void run() { while (true) { // nap for awhile db.acquireReadLock(); // you now have access to read from the database // read from the database db.releaseReadLock(); } } } Eduardo Nicola F. Zagari 62 Comunicação e Sincronização
    • public class Writer implements Runnable { private RWLock db; public Writer(RWLock db) { this.db = db; } public void run() { while (true) { db.acquireWriteLock(); // you have access to write to the database // write to the database db.releaseWriteLock(); } } } Eduardo Nicola F. Zagari 63 Comunicação e Sincronização
    • public interface RWLock { public abstract void acquireReadLock(); public abstract void acquireWriteLock(); public abstract void releaseReadLock(); public abstract void releaseWriteLock(); } Eduardo Nicola F. Zagari 64 Comunicação e Sincronização
    • public class Database implements RWLock { private int readerCount; private Semaphore mutex; private Semaphore db; public Database() { readerCount = 0; mutex = new Semaphore(1); db = new Semaphore(1); } public int acquireReadLock() { /* next slides */ } public int releaseReadLock() {/* next slides */ } public void acquireWriteLock() {/* next slides */ } public void releaseWriteLock() {/* next slides */ } } Eduardo Nicola F. Zagari 65 Comunicação e Sincronização
    • public void acquireReadLock() { mutex.acquire(); ++readerCount; // if I am the first reader tell all others // that the database is being read if (readerCount == 1) db.acquire(); mutex.release(); } public void releaseReadLock() { mutex.acquire(); --readerCount; // if I am the last reader tell all others // that the database is no longer being read if (readerCount == 0) db.release(); mutex.release(); } Eduardo Nicola F. Zagari 66 Comunicação e Sincronização
    • public void acquireWriteLock() { db.acquire(); } public void releaseWriteLock() { db.release(); } Eduardo Nicola F. Zagari 67 Comunicação e Sincronização
    • Eduardo Nicola F. Zagari 68 Comunicação e Sincronização
    •   Cinco filósofos passam a vida meditando em suas salas e, quando têm fome, vão ao refeitório, comem e voltam a meditar   Para um filósofo comer é necessário conseguir os dois chopsticks (pauzinhos chineses) que, originalmente, estão à esquerda e à direita do lugar onde se sentou   Um filósofo pode sentar em qualquer dos cinco lugares   O estoque de comida é interminável   Deve-se garantir:   exclusão mútua   não ocorrência de deadlock   não ocorrência de adiamento indefinido (starvation)   não existência de prioridade para algum filósofo   possibilidade de velocidades diferenciadas Eduardo Nicola F. Zagari 69 Comunicação e Sincronização
    • Program Tentativa_Um; var pauzinho: array[1..5] of semaforo; i: integer; Procedure filosofo(i:integer) Begin begin for i:= 1 to 5 do while TRUE do pauzinho[i] := 1; begin Cobegin Pensando; filosofo(1); P(pauzinho[i]); filosofo(2); P(pauzinho[(i+1)mod N]); filosofo(3); Comendo; filosofo(4); V(pauzinho[i]); filosofo(5); V(pauzinho[(i+1)mod N]); Coend; end; End. end; Eduardo Nicola F. Zagari 70 Comunicação e Sincronização
    •   Não funciona se os filósofos resolverem comer ao mesmo tempo e cada um pegar o pauzinho esquerdo não haverá pauzinho direito (deadlock)   Pode-se modificar o programa de tal forma que, após pegar pauzinho esquerdo, verifica-se se o pauzinho direto está livre se não, põe-se de volta o pauzinho suponha que todos peguem e testem juntos adiamento indefinido (starvation)   Se cada filósofo aguardar um tempo randômico tempo de resposta variável (além de ainda ser susceptível à falha de inanição) Eduardo Nicola F. Zagari 71 Comunicação e Sincronização
    • Program Tentativa_Dois; var lugar: semaforo; Procedure filosofo; Begin begin lugar := 1; while TRUE do Cobegin begin filosofo; Pensando; filosofo; P(lugar); filosofo; Comendo; filosofo; V(lugar); filosofo; end; Coend; end; End. Eduardo Nicola F. Zagari 72 Comunicação e Sincronização
    •   Tentativa Dois: proteção através de semáforo binário antes de começar a comer demais filósofos ficam esperando o primeiro liberar o pauzinho   Na prática, não funciona a cada instante, apenas um filósofo senta-se à mesa para comer sub-utilização dos recursos do sistema Eduardo Nicola F. Zagari 73 Comunicação e Sincronização
    • Program Tentativa_Três; var pauzinho: array[1..5] of semaforo; lugar: semaforo, i: integer; Procedure filosofo(i:integer) Begin begin lugar := 4; while TRUE do begin for i:= 1 to 5 do Pensando; pauzinho[i] := 1; P(lugar); Cobegin P(pauzinho[i]); filosofo(1); P(pauzinho[(i+1)mod N]); filosofo(2); Comendo; filosofo(3); V(pauzinho[i]); filosofo(4); V(pauzinho[(i+1)mod N]); filosofo(5); V(lugar); Coend; end; End. end; Eduardo Nicola F. Zagari 74 Comunicação e Sincronização
    •   Tentativa Três: no máximo quatro filósofos sentam-se à mesa ao mesmo tempo   Para 5 garfos disponíveis, devemos permitir que dois filósofos comam ao mesmo tempo   Não funciona apenas um irá comer por vez (posse de dois pauzinhos)   Solução não controlar os recursos, mas os estados dos filósofos... Eduardo Nicola F. Zagari 75 Comunicação e Sincronização
    • Program Solução; Cons N = 5; Pensando = 0; Com_fome = 1; Comendo = 2; Type situacao = [Pensando, Com_fome, Comendo]; var pode_sentar: array[1..5] of semaforo; estado: array[1..5] of situacao; mutex: semaforo; Begin i: integer; mutex := 1; Procedure filosofo(i:integer) for i:= 1 to 5 do begin estado[i] := Pensando; begin pode_sentar[i] := 0; while TRUE do begin end; Pensando; Cobegin Pega_pauzinho(i); filosofo(1); filosofo(2); Comendo; filosofo(3); filosofo(4); Coloca_pauzinho(i); filosofo(5); end; Coend; end; End. Eduardo Nicola F. Zagari 76 Comunicação e Sincronização
    • Procedure pega_pauzinho(i:integer); begin Procedure P(mutex); coloca_pauzinho(i:integer); estado[i] := Com_fome; begin testa(i); P(mutex); V(mutex); estado[i] := Pensando; P(pode_sentar[i]); testa((i-1) mod N); end; testa((i+1) mod N); Procedure testa(i:integer); V(mutex); begin end; if (estado[i]= Com_fome and estado[(i-1)mod N] <> Comendo and estado[(i+1) mod N] <> Comendo) then begin estado[i] := Comendo; V(pode_sentar[i]); end; end. Eduardo Nicola F. Zagari 77 Comunicação e Sincronização
    •   Dados compartilhados Semaphore chopStick[] = new Semaphore[5];   Filósofo i: while (true) { // get left chopstick chopStick[i].acquire(); // get right chopstick chopStick[(i + 1) % 5].acquire(); eating(); // return left chopstick chopStick[i].release(); // return right chopstick chopStick[(i + 1) % 5].release(); thinking(); } Eduardo Nicola F. Zagari 78 Comunicação e Sincronização
    •   Considere que, no projeto da solução do produtor-consumidor com semáforos, os 2 “downs” tenham sido trocados   Se o buffer estiver cheio deadlock   Monitor = coleção de variáveis, estruturas e procedimentos que são agrupados em um módulo ou pacote (tipo abstrato de dados com operações bem definidas para atuarem sobre sua estrutura de dados)   Um monitor é uma abstração de alto nível que provê exclusão mútua   Os procedimentos de um monitor só executam alguma tarefa quando chamados por processos (são passivos) e operam sobre variáveis comuns que constituem sua estrutura de dados Eduardo Nicola F. Zagari 79 Comunicação e Sincronização
    •   Os processos podem chamar procedimentos dos monitores, mas não têm acesso à estrutura interna dos mesmos   Somente um processo pode estar ativo em um monitor em cada instante, sendo assim, definem regiões críticas criando exclusão mútua para a estrutura de dados do monitor   Quando um processo chama um procedimento num monitor, verifica-se se outro processo está ativo no monitor   Sim: processo suspenso   Não: processo pode entrar na Região Crítica   A sincronização entre processos concorrentes se faz através de operações WAIT e SIGNAL sobre variáveis do tipo evento, definidas dentro do monitor   Uma thread (ou procedimento) que invoca x.wait é suspensa até que outra(o) invoque x.signal   Implementação: precisa de suporte da linguagem Eduardo Nicola F. Zagari 80 Comunicação e Sincronização
    •   Somente uma thread (ou procedimento) pode estar ativo dentro do monitor por vez monitor monitor-name { // variable declarations public entry p1(…) { … } public entry p2(…) { … } } Eduardo Nicola F. Zagari 81 Comunicação e Sincronização
    • Eduardo Nicola F. Zagari 82 Comunicação e Sincronização
    • procedure producer; procedure consumer; begin begin while true do while true do begin begin produce_item; ProduceConsumer.remove; ProduceConsumer.enter; consume_item; end; end; end; end; Eduardo Nicola F. Zagari 83 Comunicação e Sincronização
    • monitor ProducerConsumer condition full, empty; integer count; procedure enter; begin if count = N then wait(full); enter_item; count := count + 1; if count = 1 then signal(empty); end; procedure remove; begin if count = 0 then wait(empty); remove_item; count := count - 1; if count = N - 1 then signal(full); end; count := 0; end monitor; Eduardo Nicola F. Zagari 84 Comunicação e Sincronização
    • monitor DiningPhilosophers { int[] state = new int[5]; static final int THINKING = 0; static final int HUNGRY = 1; static final int EATING = 2; condition[] self = new condition[5]; public diningPhilosophers { for (int i = 0; i < 5; i++) state[i] = THINKING; } public entry pickUp(int i) { state[i] = HUNGRY; test(i); if (state[i] != EATING) self[i].wait; } // Continued on Next Slide Eduardo Nicola F. Zagari 85 Comunicação e Sincronização
    • public entry putDown(int i) { state[i] = THINKING; // test left and right neighbors test((i + 4) % 5); test((i + 1) % 5); } private test(int i) { if ( (state[(i + 4) % 5] != EATING) && (state[i] == HUNGRY) && (state[(i + 1) % 5] != EATING) ) { state[i] = EATING; self[i].signal; } } } Eduardo Nicola F. Zagari 86 Comunicação e Sincronização
    •   Os mecanismos anteriores permitem comunicação indireta   O mecanismo de troca de mensagens entre um processo gerente, destinado a disciplinar a utilização de determinado recurso, e os processos concorrentes pode ser usado para se obter exclusão mútua   Duas primitivas -não há compartilhamento de memória   SEND(destino, msg) destino: processo destinatário (ex.: PID) msg: mensagem que se quer enviar   RECEIVE(fonte, &msg) fonte: processo que enviou msg: mensagem retornada, se existir –  Caso não exista mensagem, o processo pode ser bloqueado até a existência de uma Eduardo Nicola F. Zagari 87 Comunicação e Sincronização
    •   Identificação dos processos: processo@máquina   Nomes de máquinas iguais domínio (proc@máq.domínio)   O armazenamento e a sincronização são feitos pelas primitivas, ou seja, pelo SO, que é o responsável   A mensagem pode se perder na rede:   mensagem de reconhecimento (acknowledgement)  se ACK não chegar, retransmite   e se a msg chega, mas o ACK se perde?  fonte envia msg novamente no de identificação de msg   Confiabilidade autenticação   Se transmissor e receptor estão na mesma máquina, o rendimento cai pelo excesso de cópias de dados Eduardo Nicola F. Zagari 88 Comunicação e Sincronização
    • #include “prototypes.h” #define N 100 #define MSIZE 4 void consumer(void) { typedef int message[4]; int item, i; void producer(void) { message m; int item; for(i=0; i<N; i++) message m; send(prod, &m); while (TRUE) { while (TRUE) { produce_item(&item); receive(prod, &m); receive(cons, &m); extract_msg(&m,item); build_msg(&m, item); send(prod, &m); send(cons, &m); consume_item(item); } } } } Eduardo Nicola F. Zagari 89 Comunicação e Sincronização