Você está na página 1de 38

Sistemas

Operacionais
Sincronização de Processos
Monitores
Relógios e Semáforos
Sincronização de Processos - Exemplo
Sincronização de Processos - Exemplo
Sincronização de Processos - Exemplo
Sincronização de Processos - Exemplo
Sincronização de Processos - Exemplo
Sincronização de Processos - Exemplo
Sincronização de Processos - Exemplo
Sincronização de Processos
• Mecanismos de busy wait
• Condições de Corrida

• Exemplo: Fila de impressão.


• Qualquer processo que queira imprimir precisa colocar o seu
documento na fila de impressão (compartilhada).
• O processo de impressão retira os documentos na ordem em
que chegaram na fila
• Se a fila é compartilhada, isto significa que seus dados, assim
como os indicadores de frente e fim da fila também o são
Sincronização de Processos
• Condições de corrida são situações em que dois ou mais
processos acessam dados compartilhados e o resultado final
depende da ordem em que os processos são executados
• Ordem de execução é ditada pelo mecanismo de escalonamento
do S.O.
• Torna a depuração difícil.
• Condições de corrida são evitadas por meio da introdução
de mecanismos de exclusão mútua:
• A exclusão mútua garante que somente um processo estará
usando os dados compartilhados num dado momento.
• Região Crítica: parte do programa (trecho de código) em
que os dados compartilhados são acessados
• Objetivo da Exclusão Mútua:
• Proibir que mais de um processo entre em sua Região Crítica
Concorrência
• Dificuldades:
• Compartilhamento de recursos globais.
• Gerência de alocação de recursos.
• Localização de erros de programação (depuração
de programas).

• Ação necessária:
• Proteger os dados compartilhados (variáveis,
arquivos e outros recursos globais).
• Promover o acesso ordenado (controle de acesso)
aos recursos compartilhados ⇒ sincronização de
processos.
Abordagens para Exclusão
Mútua
• Requisitos para uma boa solução:
• A apenas um processo é permitido estar dentro de
sua R.C. (Região Crítica) num dado instante.
• Nenhum processo que executa fora de sua região
crítica deve bloquear outro processo (ex: processo
pára fora da sua R.C.).
• Nenhuma suposição pode ser feita sobre as
velocidades relativas dos processos ou sobre o
número de CPUs no sistema.
• Nenhum processo pode ter que esperar eternamente
para entrar em sua R.C. ou lá ficar eternamente.
Tipos de Soluções
• Soluções de Hardware
• Inibição de interrupções
• Instrução TSL (apresenta busy wait)
• Soluções de software com busy wait
• Variável de bloqueio
• Alternância estrita
• Algoritmo de Decker
• Algoritmo de Peterson
• Soluções de software com bloqueio
• Sleep / Wakeup, Semáforos, Monitores
Soluções com Busy Wait
• Busy wait = espera ativa ou espera ocupada.
• Basicamente o que essas soluções fazem é:
• Quando um processo quer entrar na sua R.C. ele verifica
se a entrada é permitida. Se não for, ele espera em um
laço (improdutivo) até que o acesso seja liberado.
• Ex: while (vez == OUTRO) do {nothing};
• Conseqüência: desperdício de tempo de CPU.
• Problema da inversão de prioridade:
• Processo LowPriority está na sua R.C. e é interrompido.
• Processo HighPriority é selecionado mas entra em espera
ativa.
• Nesta situação, o processo LowPriority nunca vai ter a
chance de sair da sua R.C.
Solução de Dekker
• Trata-se da primeira solução correta para o
problema da exclusão mútua de dois processos
(proposta na década de 60).
• O algoritmo combina as ideias de variável de
bloqueio e array de intenção.
• É similar ao algoritmo anterior mas usa uma
variável adicional (vez/turn) para realizar o
desempate, no caso dos dois processos
entrarem no loop de mútua cortesia.
Algoritmo de Dekker
• Algoritmo de Dekker resolve o problema da
exclusão mútua
• Uma solução deste tipo só é aceitável se houver
um número de CPUs igual (ou superior) ao
número de processos que se devam executar no
sistema. Porquê?
• Poderíamos nos dar 'ao luxo' de consumir ciclos de
CPU,
• Situação rara na prática (em geral, há mais processos
do que CPUs)
• Isto significa que a solução de Dekker é pouco usada.
Algoritmo de Dekker
• Contudo, a solução de Dekker mostrou que é
possível resolver o problema inteiramente por
software, isto é, sem exigir instruções máquina
especiais.
• Devemos fazer uma modificação significativa
do programa se quisermos estender a solução
de 2 para N processos:
• flag[] com N posições; variável turn passa a
assumir valores de 1..N; alteração das condições de
teste em todos os processos
Solução de Peterson
• Proposto em 1981, é uma solução simples e
elegante para o problema da exclusão mútua,
sendo facilmente generalizado para o caso de
n processos.
• O truque do algoritmo consiste no seguinte:
• Ao marcar a sua intenção de entrar, o processo já
indica (para o caso de empate) que a vez é do
outro.
• Mais simples de ser verificado
• Exclusão mútua é atingida.
• Bloqueio mútuo (deadlock) é evitado.
A Instrução TSL
• TSL = “Test and Set Lock”
• Solução de hardware para o problema da exclusão mútua
em ambiente com vários processadores.
• O processador que executa a TSL bloqueia o barramento de
memória, impedindo que outras CPUs acessem a MP até que a
instrução tenha terminado.
• A instrução TSL faz o seguinte:
• Lê o conteúdo de um endereço de memória (variável
compartilhada “lock”, usada para proteger a R.C.) para um
registrador e armazena um valor diferente de zero (normalmente
1) nesse endereço.
• A instrução TSL é executada de forma atômica.
• As operações de leitura e armazenamento da variável lock são
garantidamente indivisíveis, sem interrupção. Nenhuma outra
CPU pode acessar lock enquanto a instrução não tiver terminado.
A Instrução TSL
• Vantagens da TSL:
• Simplicidade de uso (embora sua implementação em
hardware não seja trivial).
• Não dá aos processos de usuário o poder de
desabilitar interrupções.
• Presente em quase todos os processadores atuais.
• Funciona em máquinas com vários processadores.
• Desvantagens:
• Espera ocupada (busy wait).
• Possibilidade de postergação infinita (starvation)
• “processo azarado” sempre pega a variável lock com o
valor 1
Semáforos
• Mecanismo criado pelo matemático holandês
E.W. Dijkstra, em 1965.
• O semáforo é uma variável inteira que pode
ser mudada por apenas duas operações
primitivas (atômicas): P e V.
• P = proberen (testar)
• V = verhogen (incrementar).
Semáforos
• Quando um processo executa uma operação P,
o valor do semáforo é decrementado (se o
semáforo for maior que 0). O processo pode
ser eventualmente bloqueado (semáforo for
igual a 0) e inserido na fila de espera do
semáforo.
• Numa operação V, o semáforo é
incrementado e, eventualmente, um
processo que aguarda na fila de espera deste
semáforo é acordado.
Semáforos
• A operação P também é comumente
referenciada como:
• down ou wait
• V também é comumente referenciada
• up ou signal

• Semáforos que assumem somente os valores 0 e


1 são denominados semáforos binários ou
mutex. Neste caso, P e V são também chamadas
de LOCK e UNLOCK, respectivamente.
Deficiência dos Semáforos
• Exemplo: suponha que os dois down do código
do produtor estivessem invertidos.
• Neste caso, mutex seria diminuído antes de empty.
• Se o buffer estivesse completamente cheio, o
produtor bloquearia com mutex = 0.
• Portanto, da próxima vez que o consumidor tentasse
acessar o buffer ele faria um down em mutex, agora
zero, e também bloquearia.
• Os dois processos ficariam bloqueados eternamente.
• Conclusão: erros de programação com
semáforos podem levar a resultados
imprevisíveis.
Deficiência dos Semáforos
• Embora semáforos forneçam uma abstração flexível
o bastante para tratar diferentes tipos de problemas
de sincronização, ele é inadequado em algumas
situações.
• Semáforos são uma abstração de alto nível
baseada em primitivas de baixo nível, que provêm
atomicidade e mecanismo de bloqueio, com
manipulação de filas de espera e de escalonamento.
• Tudo isso contribui para que a operação seja lenta.
• Para alguns recursos, isso pode ser tolerado; para
outros esse tempo mais longo é inaceitável.
Monitores
• Sugeridos por Dijkstra (1971) e
desenvolvidos por Hoare (1974) e
Brinch Hansen (1975), são
estruturas de sincronização de alto
nível, que têm por objetivo impor
(forçar) uma boa estruturação para
programas concorrentes.
Monitores
• Motivação:
• Sistemas baseados em algoritmos de
exclusão mútua ou semáforos estão sujeitos
a erros de programação. Embora estes
devam estar inseridos no código do
processo, não existe nenhuma reivindicação
formal da sua presença. Assim, erros e
omissões (deliberadas ou não) podem
existir e a exclusão mútua pode não ser
atingida.
Monitores
• Solução:
• Tornar obrigatória a exclusão mútua. Uma maneira de
se fazer isso é colocar as seções críticas em uma área
acessível somente a um processo de cada vez.
• Idéia central:
• Em vez de codificar as seções críticas dentro de cada
processo, podemos codificá-las como procedimentos
(procedure entries) do monitor. Assim, quando um
processo precisa referenciar dados compartilhados,
ele simplesmente chama um procedimento do
monitor.
• Resultado: o código da seção crítica não é mais
duplicado em cada processo.
Monitores
• Um monitor pode ser visto como um bloco que
contém internamente dados para serem
compartilhados e procedimentos para manipular
esses dados.
• Os dados declarados dentro do monitor são
compartilhados por todos os processos, mas só
podem ser acessados por meio dos
procedimentos do monitor, isto é, a única
maneira pela qual um processo pode acessar os
dados compartilhados é indiretamente, por meio
das procedure entries.
Monitores
• As procedure entries são executadas de forma
mutuamente exclusiva. A forma de
implementação do monitor já garante a
exclusão mútua na manipulação dos seus
dados internos.

• Monitor é um conceito incluído em algumas


linguagens de programação:
• Módula, Pascal Concorrente, Euclid
Concorrente,Java.
Visão da Estrutura de um
Monitor
Monitores
• Variáveis de Condição
• São variáveis que estão associadas a
condições que provocam a suspensão e a
reativação de processos. Permitem,
portanto, sincronizações do tipo sleep-
wakeup.
• Só podem ser declaradas dentro do monitor
e são sempre usadas como argumentos de
dois comandos especiais:
• Wait (ou Delay)
• Signal (ou Continue)
Monitores
• Variáveis de Condição
• Wait (condition)
• Faz com que o monitor suspenda o processo que
fez a chamada. O monitor armazena as
informações sobre o processo suspenso em uma
estrutura de dados (fila) associada à variável de
condição.
• Signal (condition)
• Faz com quer o monitor reative UM dos processos
suspensos na fila associada à variável de
condição.
Monitores
• Variáveis de Condição
• O que acontece após um Signal
(condition)?
• Hoare propôs deixar o processo Q
recentemente acordado executar,
bloqueando o processo P sinalizador. P
deve esperar em uma fila pelo término
da operação de monitor realizada por Q.
• Fila de Sinalizadores
Monitores
• Variáveis de Condição
• O que acontece após um Signal (condition)?
• Brinch Hansen propôs que o processo P conclua a
operação em curso, uma vez que já estava em
execução no monitor (i.e., Q deve esperar). Neste
caso, a condição lógica pela qual o processo Q
estava esperando pode não ser mais verdadeira
quando Q for reiniciado.
• Simplificação: o comando signal só pode aparecer
como a declaração final em um procedimento do
monitor.
Monitores
• Variáveis de Condição
• A linguagem Concurrent Pascal adota um meio
termo entre essas duas possibilidades:
• Quando P executa um signal, a operação do monitor que
ele estava executando termina imediatamente, sendo a
execução de Q (recentemente acordado) imediatamente
reiniciada.
• Nesta solução, um processo não pode realizar duas
operações signal durante a execução de uma chamada de
procedimento de monitor (ou seja, é uma solução menos
poderosa que a proposta por Hoare).
stay @127.0.0.1

Você também pode gostar