LRM Prof. Mantovani ← Aulas da disciplina
Semana 6 · Aula 6 de 14

Sincronização e IPC

Exclusão mútua, semáforos e monitores para coordenar processos, e o problema da inversão de prioridade com sua solução por herança.

📚 Sistemas Operacionais📝 mini-quiz ao final
Objetivos da aula

O que você vai aprender

1

Explicar a condição de corrida e a necessidade de exclusão mútua.

2

Usar semáforos e monitores para sincronizar.

3

Reconhecer e resolver a inversão de prioridade.

4

Relacionar instruções atômicas de hardware às travas.

1 · Motivação

Quando 1 + 1 não dá 2

Duas threads incrementam o mesmo contador, cada uma 1000 vezes. O resultado esperado é 2000 — mas, sem cuidado, pode dar 1500, 1800, qualquer coisa. Por quê? Porque "incrementar" não é uma operação atômica.

Esta aula trata de como threads e processos coordenam o acesso a recursos compartilhados sem corromper dados — e do perigo sutil que isso traz para o tempo real: a inversão de prioridade.

2 · Mapa

Roteiro da aula

Condição
de corrida
Semáforos e
monitores
Inversão de
prioridade
Herança de
prioridade

Do problema (races) às ferramentas (semáforos, monitores, instruções atômicas) e ao caso especial do tempo real.

3 · Conceito

Condição de corrida e seção crítica

Condição de corrida. O resultado depende da ordem de execução de threads que acessam um recurso compartilhado.
Seção crítica. Trecho de código que acessa o recurso compartilhado e deve ser executado por uma thread de cada vez.
4 · Explicação

Por que o incremento não é atômico

A instrução contador++ em alto nível esconde três passos em hardware: ler o valor da memória para um registrador, somar 1, escrever de volta. Se duas threads intercalam esses passos, ambas leem o mesmo valor antigo e uma sobrescreve a outra — um incremento se perde.

A solução é garantir exclusão mútua: cercar a seção crítica de modo que apenas uma thread por vez execute aquele trecho. As propriedades desejadas são: exclusão mútua, progresso (não bloquear sem necessidade) e espera limitada (sem inanição).

5 · Exemplo

A intercalação fatal

// contador comeca em 0; esperado: 2 Thread A: le contador (0) Thread B: le contador (0) // le o mesmo valor! Thread A: soma 1 -> 1, escreve (1) Thread B: soma 1 -> 1, escreve (1) // perdeu um incremento resultado final = 1 // deveria ser 2

A ordem de execução, fora do controle do programador, mudou o resultado. Eis a condição de corrida em ação.

6 · Interativo

Passo a passo: produtor-consumidor

Passo 1
Produtor faz wait(vazio): há espaço? decrementa a contagem de vazios.
Passo 2
wait(mutex): entra na seção crítica (só ele mexe no buffer).
Passo 3
Insere o item; signal(mutex) libera a seção crítica.
Passo 4
signal(cheio): avisa que há mais um item para consumir.
Passo 5
O consumidor espelha: wait(cheio), wait(mutex), consome, signal(mutex), signal(vazio).
7 · Conceito

Semáforos e monitores

Semáforo. Variável inteira com operações atômicas wait/P (decrementa, bloqueia se ficaria negativo) e signal/V (incrementa, libera quem espera).
Monitor. Construção de alto nível que encapsula dados + operações com exclusão mútua automática e variáveis de condição.
8 · Explicação

Semáforo binário, contador e monitor

Um semáforo binário (valores 0/1) funciona como um mutex: protege uma seção crítica. Um semáforo contador conta recursos disponíveis (ex.: vagas num buffer). A operação wait/signal deve ser atômica — implementada com apoio do hardware.

// produtor-consumidor com semaforos sem vazio = N, cheio = 0, mutex = 1 produtor: wait(vazio); wait(mutex); /* produz */ signal(mutex); signal(cheio) consumidor: wait(cheio); wait(mutex); /* consome */ signal(mutex); signal(vazio)

O monitor eleva o nível de abstração: a exclusão mútua é embutida e variáveis de condição (wait/signal sobre condições) coordenam a espera por eventos.

9 · Analogia

A tranca do banheiro

🚻 Analogia
A seção crítica é como um banheiro de uma pessoa. A tranca (exclusão mútua) garante que só uma entre por vez. Sem tranca, duas entram e o caos se instala (condição de corrida). O semáforo contador seria um vestiário com N cabines: enquanto houver cabine livre, alguém entra; quando lotam, os próximos esperam.
10 · Comparação

Semáforo vs. monitor

AspectoSemáforoMonitor
NívelBaixo nívelAlto nível
Exclusão mútuaManual (o programador chama wait/signal)Automática (embutida)
Risco de erroAlto (esquecer um signal trava tudo)Menor (a estrutura cuida)
Espera por condiçãoCom semáforos auxiliaresVariáveis de condição nativas
11 · Fluxo

Da instrução atômica à trava

Instrução atômica
(TAS / CAS)
Lock /
mutex
Semáforo /
monitor
Programa
correto
💡
Em hardware, instruções atômicas como test-and-set (TAS) e compare-and-swap (CAS) leem e escrevem em um único passo indivisível — a base para construir travas sem condição de corrida na própria trava.
12 · Aprofundamento

A inversão de prioridade

Inversão de prioridade. Uma tarefa de alta prioridade fica bloqueada esperando um recurso travado por uma de baixa prioridade, que por sua vez é preemptada por tarefas de prioridade intermediária — atrasando indefinidamente a tarefa alta.

É um problema clássico e perigoso em tempo real: a tarefa de alta prioridade "espera" não pela baixa diretamente, mas pelas médias que monopolizam a CPU enquanto a baixa segura o recurso. O prazo da tarefa alta pode estourar.

13 · Interativo

Verifique seu entendimento

Na inversão de prioridade, o que de fato atrasa a tarefa de ALTA prioridade?

A baixa segura o lock; as médias a preemptam e impedem que ela libere o recurso. A alta espera por todas elas — daí a "inversão".
14 · Caso prático

Mars Pathfinder (1997)

A sonda Mars Pathfinder começou a reiniciar repetidamente em Marte. A causa: inversão de prioridade. Uma tarefa de alta prioridade (gestão do barramento) esperava um mutex segurado por uma tarefa de baixa prioridade (meteorologia), que era constantemente preemptada por tarefas de prioridade média. Um watchdog detectava o atraso e reiniciava o sistema.

A correção foi enviada remotamente: ativar a herança de prioridade no semáforo. É o exemplo canônico de por que sincronização em tempo real é assunto sério — aqui, a milhões de quilômetros de distância.

15 · Erros comuns

Armadilhas de sincronização

⚠️
Cuidado:
• Esquecer um signal → o recurso fica travado para sempre (deadlock).
• Adquirir locks em ordens diferentes em threads distintas → deadlock (Aula 7).
• Seções críticas grandes demais → serializam o programa e matam o paralelismo.
• Ignorar a inversão de prioridade em sistemas de tempo real.
16 · Dicas

Boas práticas de exclusão mútua

Mantenha a seção crítica curta: trave, faça só o estritamente necessário, libere. Quanto menor o tempo segurando o lock, menor a contenção e o risco de inversão. Adquira múltiplos locks sempre na mesma ordem global para evitar deadlocks. E prefira abstrações de alto nível (monitores) quando possível.
17 · Interativo

Revele a solução

Como a herança de prioridade resolve a inversão?
A tarefa de baixa prioridade que segura o recurso herda temporariamente a prioridade da tarefa de alta que está esperando. Assim, ela não pode mais ser preemptada pelas tarefas de prioridade média: termina rapidamente a seção crítica, libera o recurso e volta à sua prioridade original. A tarefa de alta então prossegue, dentro do prazo.
18 · Flashcards

Revisão relâmpago

Condição de corridavirar
Resultado depende da ordem de execução de threads sobre um recurso compartilhado.
wait/Pvirar
Decrementa o semáforo; bloqueia se o recurso não está disponível.
CASvirar
Compare-and-swap: lê e escreve atomicamente; base de travas e estruturas lock-free.
Herança de prioridadevirar
A tarefa que segura o recurso herda a prioridade alta de quem espera, liberando-o rápido.
19 · Conexões

Como isto se liga ao curso

A sincronização conecta:

  • As threads e a memória compartilhada (Aula 4), que tornam as races possíveis.
  • As instruções atômicas de hardware (Aula 1), que sustentam as travas.
  • Os deadlocks (Aula 7), que surgem de locks mal coordenados — wait/signal e ordem de aquisição importam.
20 · Síntese

Resumo da aula

🔑
Condições de corrida exigem exclusão mútua na seção crítica. Semáforos (wait/signal) e monitores coordenam o acesso compartilhado, apoiados por instruções atômicas de hardware (TAS, CAS). Em tempo real, a inversão de prioridade ameaça os prazos — como no Mars Pathfinder — e a herança de prioridade a resolve. Locks mal usados, porém, levam a deadlocks: o tema da próxima aula.
Mão na massa · colaborativo

Atividade em grupo · Resolvendo a inversão

Em trios, encenem e resolvam um caso de inversão de prioridade.

⏱️ 25 min👥 trios🧩 simulação

Roteiro

  1. Definam 3 tarefas: H (alta), M (média) e L (baixa); L segura um mutex que H precisa.
  2. Tracem a linha do tempo mostrando H bloqueada por L enquanto M roda.
  3. Apliquem herança de prioridade e refaçam a linha do tempo.
  4. Comparem a latência de H nos dois casos.
Tarefa Hrepresenta a alta prioridade
Tarefa Lsegura o recurso
Observadormede a latência
📤 Entrega: Duas linhas do tempo (com e sem herança) e a latência de H em cada uma.
Teste seu conhecimento

Mini-quiz · Aula 6

20 questões sobre esta aula. Escolha e veja a explicação na hora.

0/20

📌 Resumo — leve isto para a prova

  • Condições de corrida exigem exclusão mútua na seção crítica.
  • Semáforos (wait/signal) e monitores coordenam o acesso compartilhado.
  • Instruções atômicas de hardware (TAS, CAS) são a base das travas.
  • A inversão de prioridade ameaça o tempo real; a herança de prioridade a resolve.
  • Locks mal coordenados levam a deadlocks; seções críticas curtas reduzem riscos.