Você está na página 1de 4

Questão 1

a) As três threads tem praticamente o mesmo tipo de comportamento, apenas


mudando a variável de acordo com seu tipo. A Thread A usa a variável a, a Thread
B usa a variável b e a Thread C usa a variável c.
A condição do problema pede que apenas threads do mesmo tipo acessem o
recurso ao mesmo tempo.

Nesse trecho de código existe exclusão mútua no bloco 1 e no bloco 2 através do


uso de semáforos. Quando uma thread do tipo A chega no sem_wait do primeiro
bloco, significa que só uma thread pode estar naquele pedaço de código pois o
semáforo foi inicializado com 1. Chegando no sem_post do primeiro bloco o valor
que era 0 passa a ser 1 e manda um sinal para que se houver thread do tipo A
esperando para entrar nesse seção crítica, pode entrar. O uso do recurso fica fora
do bloco de seção crítica, dessa forma permitindo que threads do mesmo tipo
acessem o recurso ao mesmo tempo.
Também não há condição de corrida ou deadlocks por conta do mecanismo da
seção crítica. Para permitir alteração na variável a, usa-se o semáforo emA e
sempre em uma seção crítica que é feito o bloqueio e liberação do rec.
Essa explicação é a mesma para a Thread B e C, já que são praticamente o mesmo
código.

b) Sim, pode ter um starvation na situação que o uso do recurso é uma tarefa longa e
demorada. Dessa forma o semáforo rec fica “preso” por bastante tempo e as outras
threads demoram a poder usar.
c) Se rec fosse inicializado com 0 teríamos a situação de deadlock. No código acima a
thread A ficaria bloqueada no sem_wait(&rec) e não teria nenhuma thread para
liberá-la.
d) Se rec fosse inicializada com mais de um sinal, significaria que mais de uma thread
(de tipos diferentes) poderia acessar o recurso ao mesmo tempo, contrariando o que
o problema queria resolver.

Questão 2
a) O problema ocorre na linha 11 do consumidor que faz a verificação de uma variável
global fora da seção crítica. Podemos exemplificar: Digamos que tem elementos no
buffer e a thread do consumidor executa até a linha 9, liberando o semáforo s. Em
seguida o consumidor executa a função consome_item da linha 10, digamos essa
função demore e que a linha 11 só é executada depois que prod executar a linha 8
dele, que é incrementar n. Dessa forma, n não vai ser mais 0 e com isso não deixa
em espera o semáforo d, causando problemas nesse mecanismo.

b)

Questão 3

a)
b) Usei como base o código passado em aula de leitor/escritor com semáforos. a partir
desse código, adicionei o semáforo sem_prioridade que é inicializado com 1 (que
nem todos os semáforos) e ele dá acesso exclusivo ao mecanismo já existente da
thread leitora, antes da parte a ser lida. Isso garante que só uma thread consiga
acessar essa parte para fazer o bloqueio da thread escritora (no primeiro leitor).
Depois que a thread faz a leitura, é decrementado o número de leitores e sendo a
última, é feito a liberação do escritor.
Já na thread escritora que é onde há mais modificações. Primeiro, adicionamos um
semáforo responsável só pela exclusão mútua para alterar o número de escritores
(não tinha antes). Esse número de escritores é necessário para identificar se há um
escritor e no primeiro já há o bloqueio do semáforo de prioridade, que afeta a thread
leitora, bloqueando-a. E também para que haja uma fila de espera de escritores.
Depois que o número de escritores é incrementado e no primeiro escritor é
bloqueado, é liberado o semáforo da exclusão mútua e inicializa o semáforo que faz
o bloqueio da escrita em si. Assim que a escrita termina libera o semáforo que
bloqueia a escrita e é feita novamente uma alteração no número de escritores,
decrementando. Se o número de escritores for zero, ou seja, for o último escritor ali,
libera o semáforo de prioridade e com isso os leitores podem iniciar. Libera também
o semáforo de número de escritores após alteração.
O mecanismo de não deixar sempre os leitores bloqueando os escritores está no
semáforo de prioridade. Ele que bloqueia quando o primeiro escritor começa e
desbloqueia quando o último escritor sai. E o leitor sempre olha esse semáforo
quando é iniciado.

Questão 4
a) O semáforo x é responsável pela seção crítica de alteração e visualização da
variável aux. A variável aux é responsável por guardar o número de threads em
espera. Quando aparece no código o semáforo x bloqueia para que ninguém acesse
essa variável, e foi inicializado corretamente.
O semáforo h é responsável pelo mecanismo de bloqueio da thread, ela bloqueia a
thread quando chama a função wait e desbloqueia uma quando chama a função
notify e desbloqueia todas quando chama a função notifyAll. Foi inicializada
corretamente já que no primeiro sem_wait ele de fato bloqueia (comportamento
esperado).
O semáforo s é responsável por garantir que as notificações (notify e notifyAll) sejam
entregues e trabalha junto com o semáforo x que decrementa o aux. Foi inicializado
corretamente já que no começo não há nenhuma thread bloqueada;
b) Sim, conforme explicado acima, cada um dos semáforos tem a sua função de
garantir esse tipo de comportamento.
c) Não há a possibilidade, cada um dos semáforos tem a sua configuração e garante
que não há deadlock ou condição de corrida.
O x por exemplo, começa e termina na mesma função, não tendo problemas quando
a acúmulo. O s e x tem mecanismos específicos para que não fique sobrando ou
faltando sinais.
Quando uma thread chama o wait o h fica aguardando um sinal e quando é
chamado o notify ou notifyAll, esse desbloqueio é feito.
Mesmo quando a chamada dessas funções por fora for errônea, não terá problemas.
Por exemplo, chama o wait uma vez depois o notify e o notifyAll em seguida, o uso
da variável aux faz o controle para que não haja acúmulo de sinais, fazendo a
liberação apenas dos sinais necessários.

Você também pode gostar