Outra questão de fundamental importância, que deve ser considerada no projeto e construção de uma linguagem de programação distribuída, é a maneira como os trechos de programas, que estão rodando em paralelo em diferentes processadores, vão cooperar. Dois tipos de interação são necessários nessa cooperação: a comunicação e o sincronismo. Usualmente, os mecanismos destinados a comunicação e sincronização entre processos, por estarem fortemente relacionados, são tratados conjuntamente.
Para mostrar isso vamos explicar primeiro o que é uma Seção Crítica.
Cada processo possui um segmento de de código, chamado Seção Crítica, onde o processo pode alterar variáveis comuns, como por exemplo atualizar uma tabela, gravar um arquivo, implementar uma lista, etc. O recurso do sistema é que, quando um processo está executando em sua seção critica, nenhum outro processo tem permissão para executar na sua seção crítica ou seja dois processos não podem executar suas sessões críticas ao mesmo tempo.
O Problema da seção crítica é projetar um protocolo que os processos possam utilizar para a cooperção. Uma Solução para o problema, precisa satisfazer os três requisitos a seguir:
1. Exclusão mútua. Se o processo Pi está executando em sua seção critica, então nenhum outro poderá executar em suas seções criticas.
2. Progresso. Se nenhum processo estiver executando em sua seção critica e alguns processos quiserem entrar em suas seções criticas, então somente os processos que não estão executando em suas seções restantes poderão participar da decisão sobre qual entrará em sua seção critica em seguida
3. Espera limitada. Existe um limite no número de vezes que outros processos têm permissão para entrar em suas seções criticas após um processo ter feito uma requisição para entrar em sua seção critica e antes de essa requisição ser atendida
Solução de Peterson
Uma solução clássica baseada em software para o problema da seção crítica. Ela é restrita a dois processos que alternam a execução entre suas seções críticas e as seções restantes.
A solução consiste em numerar os processos e fazer com que ele, antes de entrar em sua seção crítica, execute uma rotina de permissão com o seu número (Processo1 – nº 1) para poder entrar em sua seção crítica. Ao terminar a utilização da seção crítica ele grava o seu número e sai da seção crítica liberando assim para o outro processo entrar.
Dessa forma Peterson evita que dois processos entrem ao mesmo tempo na seção crítica. O Problema dessa Solução é que os próprios processos devem pedir permissão pra entrar e falar que já saíram da seção crítica, caso um deles for mal programado pode monopolizar a seção crítica.
Hardware de Sincronismo
O sincronismo em hardware consiste em desligar as interrupções por outro processo durante a execução de uma seção crítica, o que permite assegurar que todas as instruções do processo que esta executando seriam efetuadas. Infelizmente esse recurso é demorado e não é viável em um ambiente multiprocessado.
As vantagens desse sincronismo é:
Aplicável a qualquer número de processos em mono ou em sistemas multiprocessador que partilhem a mesma memória principal;
Simples e fácil de verificar;
Permite o suporte a n secções críticas.
As desvantagens são:
Espera activa consumo tempo de processador;
Num sistema escalonado por prioridades se um processo de baixa prioridade está esperando a secção crítica e um outro processo de mais alta prioridade também está esperando, então o processo de mais alta prioridade retêm o processador, ficando em espera ativa até que a secção crítica seja libertada, o que nunca acontecerá;
Deadlock.
Semáforos
É uma ferramenta de sincronismo que contorna a dificuldade da programação de aplicação do Sincronismo de Hardware. É um mecanismo de sincronização sem espera ativa.
Para evitar a espera ativa, um processo que espera a libertação de um recurso deve ser bloqueado, passando assim para o estado de Waiting, ou seja, ele vai esperar o processo terminar de executar e liberar o recurso de que precisa para ele executar.
O semáforo inclui também uma fila de espera associada ao Waiting , esta fila contém todos os descritores dos processos bloqueados no semáforo.
Quando o semáforo deixa de estar bloqueado é escolhido o processo da fila de espera do semáforo, um processo de acordo com um critério de Prioridades e de acordo com a ordem da fila LIFO (Last in, First out).
Deadlock e Starvation
A implementação de um Semáforo com fila de espera pode resultar em uma situação em que dois ou mais processos aguardam indefinidamente por um evento que só poderá ser causado por um dos processos aguardando. Quanto este estado é alcançado, considera-se que os processos estão em um Deadlock. Exemplo: Temos 2 processos P1 e P2. Digamos que para P1 executar ele precisa de um recurso que P2 libera e para P2 executar ele precisa de um recurso que P1 libera, o que resulta em um Deadlock.
Os principais eventos de que falamos aqui é aquisição e liberação de recursos, mas outros eventos podem causar Deadlock.
Outro problema relacionado a deadlock é o bloqueio indefinido ou Starvation, uma situação em que os processos esperam indefinidamente dentro do semáforo. O Starvation pode ocorrer se acrescentarmos ou removermos processos da lista associada a um semáforo na ordem LIFO.
Problemas Clássicos de Sincronismo
Citaremos agora uma série de problemas de sincronismos diferentes como exemplos para uma grande classe de problemas de controle de concorrência.
Esses problemas são usados para testar quase todo esquema de sincronismo recém-proposto.
Partilha de recursos limitados;
Sincronização de execução;
Problema do Produtor/Consumidor(Bounded-buffer);
Problema dos Leitores e Escritores;
Jantar dos filósofos (Dining-Philosophers);
Barbeiro Dorminhoco.
Nenhum comentário:
Postar um comentário