Monitores Semáforos Semáforos são ferramentas importantes para implementar exclusão mútua. Mas pode ser difícil utilizá-los corretamente em um programa. Estão sujeitos a erros de programação. Principalmente se necessário definir várias RCs. Como tornar o uso de semáforos mais fácil/amigável ? Monitores É um construtor de linguagem de programação que oferece a funcionalidade dos semáforos. Maior facilidade de utilização por parte do programador. Não tem em muitas linguagens de programação, mas em Java codificar as seções críticas como procedimentos do monitor pode tornar mais modular. Quando um processo precisa referenciar dados compartilhados chama um procedimento do monitor. Módulos de linguagens de programação que fornecem uma funcionalidade equivalente aos semáforo. Monitores O monitor é um conjunto de procedimentos, variáveis e inicialização definidos dentro de um módulo um processo entra no “monitor”, chamando um dos seus procedimentos. Como se fosse uma classe. Pode ser uma classe. A característica mais importante do monitor é a exclusão mútua automática entre os seus procedimentos. Basta codificar as regiões críticas como procedimentos do monitor e se irá garantir a exclusão mútua. Como semáforos, só um processo pode estar executando no monitor de cada vez, sendo que outros processos que chamarem o monitor, ficarão bloqueados. Oferece, portanto, exclusão mútua. Monitores Variáveis compartilhadas podem ser protegidas, especificando-as através do monitor. Um processo pode ser bloqueado quando tentar entrar no monitor, mas este está sendo utilizado por outro. Quando um processo termina de usar o monitor, tem que liberá-lo. Monitores monitor monitor-name { declaração de variáveis compartilhadas procedure P1 (…) { ... } procedure P2 (…) { ... } procedure Pn (…) { ... } { código de inicialização } } Leitores e Escritores Outra situação que ocorre com frequência em sistemas concorrentes é o problema dos leitores/escritores. Neste caso, um conjunto de processos ou threads acessam de forma concorrente uma área de memória comum (compartilhada), na qual podem fazer leituras ou escritas de valores. As leituras podem ser feitas simultaneamente, pois não interferem umas com as outras, mas as escritas têm de ser feitas com acesso exclusivo à área compartilhada, para evitar os erros de inconsistência. Observações Três tipos de soluções: • Priorização dos leitores: sempre que um leitor quiser ler e não houver escritor escrevendo (pode haver escritor esperando), ele tem acesso à fila. Nesta solução, um escritor pode ter de esperar indefinidamente (inanição, ou starvation), pois novos leitores sempre chegam. • Priorização dos escritores: quando um escritor desejar escrever, mais nenhum leitor pode fazer leituras enquanto o escritor não for atendido. Nesta solução, um leitor pode ter de esperar indefinidamente (inanição), pois novos escritores sempre chegam. • Prioridades iguais: não há risco de inanição, pois leitores e escritores têm as mesmas chances de acesso à fila; pode haver uma queda de desempenho em relação às soluções anteriores. Leitores e Escritores Escritores precisam de acesso exclusivo ao recurso, ou seja, sua região crítica Leitores podem acessar o recurso concorrentemente (time- sliced default do processador) com outros leitores. Monitores Uma thread/processo entra em um monitor, chamando qualquer um de seus procedimentos. Um processo está em um monitor, quando está pronto ou executando. Um ponto de entrada somente, para garantir exclusão mútua. Outros processos ficam em fila de bloqueados se tentarem entrar no Monitor. Monitores Para implementar a sincronização é necessário utilizar variáveis de condição, só acessíveis dentro do monitor Variáveis de condição são tipos de dados especiais dos monitores operados por duas instruções Wait e Signal (notify). Wait(C): suspende a execução do processo, colocando-o em estado de espera associado a condição C Signal(C): permite que um processo bloqueado por wait(C) continue a sua execução. Se existir mais de um processo/thread bloqueado, apenas um é liberado para execução. Monitores em Java Uma linguagem atual que oferece o uso de monitores é Java. Métodos são colocados em estado de monitor através da palavra chave synchronized . Métodos que testam variáveis de condição são: wait(), notify(), and notifyAll() wait( ) – o respectivo thread vai para bloqueado (estado sleep) até que algum outra thread que entrou no monitor dê notify( ). notify( ) – acorda o primeiro thread que chamou um wait( ) no mesmo objeto. notifyAll( ) – acorda todos as threads que chamaram wait( ), sendo que a thread de maior prioridade executa primeiro.