Java/Concorrência/Threads
Java⏱ ~2 min de leitura

Threads

Paralelismo, sincronização e race conditions

Threads permitem que um programa execute múltiplas tarefas em paralelo. A JVM cria pelo menos uma thread (a main thread). Você pode criar threads adicionais estendendo Thread ou implementando Runnable — a segunda é preferida por seguir o princípio de composição sobre herança.

O maior desafio no multithreading é a concorrência: quando múltiplas threads acessam e modificam o mesmo recurso compartilhado, podem ocorrer race conditions — resultados incorretos devido a ordem não determinística de execução. A palavra-chave synchronized garante exclusão mútua, permitindo apenas uma thread por vez em um bloco.

Criar threads manualmente é de baixo nível. Em aplicações reais, use o framework Executor: ExecutorService gerencia um pool de threads reutilizáveis, evitando o overhead de criar e destruir threads continuamente.

Exemplo.java
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;

// ── Runnable com lambda (preferido) ──────────────
ExecutorService executor = Executors.newFixedThreadPool(4);

for (int i = 0; i < 8; i++) {
    final int id = i;
    executor.submit(() -> {
        System.out.printf("Tarefa %d em %s%n",
            id, Thread.currentThread().getName());
    });
}
executor.shutdown();
executor.awaitTermination(10, TimeUnit.SECONDS);

// ── Race condition e sincronização ────────────────
class Contador {
    private int valor = 0;

    // synchronized: apenas uma thread por vez
    public synchronized void incrementar() { valor++; }
    public synchronized int getValor() { return valor; }
}

// ── AtomicInteger: alternativa thread-safe e rápida ─
AtomicInteger atomico = new AtomicInteger(0);
atomico.incrementAndGet(); // operação atômica, sem lock

// ── Thread.sleep: pausa a thread atual ───────────
try {
    Thread.sleep(100); // 100 ms
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}
💡 Dica pro

Nunca compartilhe estado mutável entre threads sem sincronização. Prefira objetos imutáveis, AtomicInteger, ou as estruturas de java.util.concurrent. Bugs de concorrência são difíceis de reproduzir e debugar.

Recompensa+45 XP+exercícios