Pular para o conteúdo principal

Questão de Sistemas Operacionais — Geral — FUNDATEC 2026

Sistemas OperacionaisGeral
Código
qa433509
Banca
FUNDATEC
Órgão
IFC
Ano
2026
Cargo
PEBTT ( )

Analise o seguinte programa escrito em linguagem C, executado em ambiente Linux e utilizando a biblioteca POSIX Threads (pthreads):

 

#include <stdio.h>
#include <pthread.h>

 

pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;

 

void* thread1(void* arg){
pthread_mutex_lock(&m1);
printf("Thread 1 bloqueou m1\n");
pthread_mutex_lock(&m2);
printf("Thread 1 bloqueou m2\n");
pthread_mutex_unlock(&m2);
pthread_mutex_unlock(&m1);
return NULL;
}

 

void* thread2(void* arg){
pthread_mutex_lock(&m2);
printf("Thread 2 bloqueou m2\n");
pthread_mutex_lock(&m1);
printf("Thread 2 bloqueou m1\n");
pthread_mutex_unlock(&m1);
pthread_mutex_unlock(&m2);
return NULL;
}

 

int main(){
pthread_t t1, t2;
pthread_create(&t1,NULL,thread1,NULL);
pthread_create(&t2,NULL,thread2,NULL);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
return 0;
}

 

Considerando a execução concorrente das threads, assinale a alternativa correta.

  1. AO uso de pthread_mutex_lock impede automaticamente a ocorrência de deadlock.
  2. BO programa apresenta erro de compilação devido ao uso simultâneo de dois mutex.
  3. CO programa executará sempre na mesma ordem, primeiro thread1 e depois thread2.
  4. DO programa sempre executará corretamente, pois cada thread libera os mutex ao final.
  5. EO programa pode entrar em deadlock, caso cada thread adquira um mutex diferente e aguarde indefinidamente pelo outro.
Revelar gabarito e comentário

GabaritoE — O programa pode entrar em deadlock, caso cada thread adquira um mutex diferente e aguarde indefinidamente pelo outro.

Comentário gerado por IA. É um apoio ao estudo, ancorado em fontes, mas pode conter imprecisões — confira sempre na fonte oficial (lei, súmula, edital e gabarito da banca). Encontrou um erro? Use “Reportar”.

Deadlock em programas com múltiplos mutexes (pthreads)

Gabarito: letra E. O programa pode entrar em deadlock porque as duas threads adquirem os mutexes em ordem inversa: a thread 1 bloqueia m1 e depois m2, enquanto a thread 2 bloqueia m2 e depois m1. Se cada uma conseguir segurar um mutex e ficar esperando pelo outro, nenhuma consegue prosseguir — é a condição clássica de espera circular, um dos quatro requisitos do deadlock. O uso de pthread_mutex_lock não impede deadlock; ele apenas garante exclusão mútua na seção crítica.

O deadlock é uma condição em que duas ou mais threads (ou processos) ficam permanentemente bloqueadas, cada uma esperando por um recurso que a outra detém. Para que ocorra, quatro condições precisam ser satisfeitas simultaneamente: exclusão mútua (cada recurso só pode ser usado por uma thread por vez), posse e espera (a thread detém um recurso e espera por outro), não preempção (o recurso só é liberado voluntariamente) e espera circular (existe um ciclo de threads esperando por recursos umas das outras). No programa, as duas primeiras condições são garantidas pelos mutexes; a não preempção é o comportamento padrão do pthread_mutex_lock; e a espera circular surge justamente pela ordem invertida de aquisição.

Na prática, o cenário de deadlock ocorre assim: a thread 1 executa pthread_mutex_lock(&m1) e consegue, imprimindo "Thread 1 bloqueou m1". Simultaneamente, a thread 2 executa pthread_mutex_lock(&m2) e consegue, imprimindo "Thread 2 bloqueou m2". Agora, a thread 1 tenta pthread_mutex_lock(&m2), mas m2 está com a thread 2; a thread 2 tenta pthread_mutex_lock(&m1), mas m1 está com a thread 1. Ambas ficam bloqueadas indefinidamente, e o programa nunca termina — o pthread_join na main nunca retorna. Esse é o exemplo canônico de deadlock por inversão de ordem de aquisição de locks.

A distinção que importa aqui é entre deadlock e race condition. No deadlock, as threads ficam paradas esperando umas pelas outras; na race condition, elas competem pelo mesmo recurso e o resultado depende da ordem de execução, mas não há bloqueio permanente. O programa apresentado não tem race condition nos mutexes (cada um protege uma seção crítica distinta), mas tem risco de deadlock. Outra distinção relevante é entre pthread_mutex_lock (bloqueante) e pthread_mutex_trylock (não bloqueante): o trylock retorna erro se o mutex estiver ocupado, permitindo que o programador evite o deadlock com uma estratégia de recuo — mas o programa usa apenas o lock bloqueante.

A pegadinha que a banca explora é a falsa sensação de segurança: como cada thread libera os mutexes ao final, o candidato pode achar que o programa "sempre executará corretamente". Mas a liberação só ocorre se a thread conseguir adquirir AMBOS os mutexes; se ficar esperando pelo segundo, nunca chega ao unlock. A ordem de aquisição é o fator decisivo: quando as threads adquirem os recursos na mesma ordem, não há ciclo; quando adquirem em ordens diferentes, o deadlock se torna possível. Guarde essa fronteira — é exatamente nela que as alternativas se dividem.

1Condições (4)
Exclusão mútua
Posse e espera
Não preempção
Espera circular
2No programa
Thread 1: m1 → m2
Thread 2: m2 → m1
Ordem invertida → ciclo
3Prevenção
Ordem global única
trylock com recuo
Algoritmo do banqueiro
Deadlock
LEVELsoulevel.com.br
Deadlock: Condições (4) (Exclusão mútua, Posse e espera, Não preempção, Espera circular); No programa (Thread 1: m1 → m2, Thread 2: m2 → m1, Ordem invertida → ciclo); Prevenção (Ordem global única, trylock com recuo, Algoritmo do banqueiro)

Alternativa A — ❌ Incorreta

Afirma que pthread_mutex_lock impede automaticamente a ocorrência de deadlock. Isso é falso: o lock apenas garante exclusão mútua — se o mutex estiver ocupado, a thread bloqueia. Ele não tem nenhuma lógica de prevenção de deadlock; pelo contrário, o uso ingênuo de múltiplos locks em ordens diferentes é justamente o que cria o deadlock. A prevenção exige técnicas como adquirir os locks sempre na mesma ordem global, usar trylock com recuo, ou empregar algoritmos como o do banqueiro.

Alternativa B — ❌ Incorreta

Afirma que o programa apresenta erro de compilação pelo uso simultâneo de dois mutex. Não há erro de compilação: a linguagem C permite declarar e usar múltiplos mutexes normalmente. O programa compila e executa; o problema é de lógica concorrente (deadlock em tempo de execução), não de sintaxe. A inicialização com PTHREAD_MUTEX_INITIALIZER é válida para mutexes estáticos, e as chamadas pthread_mutex_lock/unlock estão corretas sintaticamente.

Alternativa C — ❌ Incorreta

Afirma que o programa executará sempre na mesma ordem, primeiro thread1 e depois thread2. Isso é falso porque a criação de threads com pthread_create não garante ordem de execução: o escalonador do sistema operacional decide qual thread roda primeiro, e isso pode variar a cada execução. Não há nenhuma sincronização inicial que force a thread 1 a começar antes da thread 2. A ordem de execução é não determinística.

Alternativa D — ❌ Incorreta

Afirma que o programa sempre executará corretamente, pois cada thread libera os mutex ao final. O erro está no "sempre": a liberação só acontece se a thread conseguir adquirir os dois mutexes. No cenário de deadlock descrito, cada thread fica bloqueada esperando o mutex da outra e nunca chega ao unlock. O programa pode executar corretamente em algumas execuções (quando uma thread consegue os dois locks antes da outra), mas não é garantido — o deadlock é uma possibilidade real.

Alternativa E — ✅ Correta ⟵ GABARITO

Esta é a descrição precisa do deadlock: "O programa pode entrar em deadlock, caso cada thread adquira um mutex diferente e aguarde indefinidamente pelo outro." Exatamente o que acontece: a thread 1 adquire m1 e espera m2; a thread 2 adquire m2 e espera m1. Forma-se um ciclo de espera — a condição de espera circular — e ambas ficam bloqueadas para sempre. O pthread_join na main nunca retorna, e o programa trava. A palavra-chave é "pode": o deadlock não é garantido (depende do escalonamento), mas é uma possibilidade concreta.

NÃO CAIA NESSA!

A banca explora a falsa sensação de segurança de que "liberar os mutex ao final" garante a corretude. O candidato que não percebe a ordem invertida de aquisição (m1→m2 na thread 1 e m2→m1 na thread 2) tende a marcar a alternativa D. A pegadinha está em confundir "liberar ao final" com "sempre conseguir chegar ao final" — no deadlock, a thread nunca chega ao unlock.

PEGA ESSA DICA!

Para identificar deadlock em questões de concorrência, verifique a ordem de aquisição dos locks em cada thread. Se as ordens forem diferentes (ex.: A→B em uma, B→A em outra), há risco de espera circular. Desenhe o grafo de alocação de recursos: se houver um ciclo, há deadlock. Na prova, procure sempre o par de threads que adquire recursos em ordens opostas — é o padrão clássico.

Gabarito: letra E

Link permanente: /questoes/qa433509