O problema dos Leitores/Escritores é um dos mais conhecidos sobre Programação Concorrente. Este problema considera a existência de vários processos que tentam aceder a uma zona de memória partilhada, uns para ler, outros para escrever. O que se pretende é que um leitor e um escritor não colidam na sua actividade para que não se corra o risco de um ir ler aquilo que outro ainda não acabou de escrever, ou de um escritor ir escrever sobre dados ainda não lidos pelo processo leitor.
No entanto, não parece haver impedimento algum para que, pelo menos os leitores, não possam aceder em simultâneo à referida zona de memória partilhada, bastando para tal que, um processo que pretenda ler, se certifique da presença de algum outro leitor ou da ausência de escritores.
O que não podemos permitir é que mais do que um escritor tenha acesso simultâneo. Isto poderia conduzir a uma alteração indevida do valor partilhado.
Surge, então, um novo cenário em que vários leitores podem estar em simultâneo na secção crítica, enquanto que não se pode permitir a entrada a mais do que um escritor de cada vez, bem como a permanência simultânea de processos de tipos distintos (um leitor e um escritor, por exemplo). Variações a este caso, são a concessão de prioridade a leitores ou a escritores. Isto vem evitar que os leitores, por exemplo, ocupem de tal forma a secção partilhada que não deixem espaço para que os escritores lá possam entrar.
O que é importante referir após a apresentação destes exemplos é que, além de termos
de recorrer aos semáforos para controlar o acesso dos vários processos à memória
partilhada, temos também de garantir, nas várias versões apresentadas, uma exclusão
mútua às variáveis auxiliares necessárias para o controle de entrada e saída.
Neste exemplo, existem dois processos a tentarem escrever e ler de um buffer comum.
O objectivo, aqui, é não deixar que um processo lá vá ler antes do outro lá ter
escrito ou que um vá tentar escrever antes do outro o ter lido.
Quando um processo lá escreve, assinala o facto para que o outro possa lá ir ler os
dados escritos. Nessa altura, esse, retira o sinal, de forma a que tanto um como o
outro possam voltar a utilizar o buffer para escrita. É de referir que um processo
não poderá ler aquilo que escreve, aliás tal não teria qualquer sentido.
O jantar dos filósofos, o mais famoso dos problemas clássicos de programação
concurrente, apresenta, mais uma vez, a competição por um conjunto de recursos
- neste caso os garfos. Na verdade, os filósofos não podem comer todos ao mesmo
tempo já que não há "garfos" que cheguem para todos. Além disso é preciso garantir
que os filósofos não se impeçam uns aos outros de comer entrando num
deadlock.
Neste exemplo, a cada filósofo é atribuído um número identificador. Para evitar situções
de deadlock todos os filósofos com número par tentam agarrar primeiro no garfo à sua esquerda e os
ímpares tentam agarrar primeiro no garfo à direita.