Data races causam comportamento indefinido. Toda variavel mutavel compartilhada entre threads precisa de sincronizacao β€” lock, Interlocked, ou colecoes concorrentes.

Thread vs Task vs ThreadPool

Use Task (thread pool) para a maioria do trabalho paralelo. Thread bruto so quando voce precisa de controle de lifetime/afinidade.

AspectoThreadTask (ThreadPool)
CriacaoCria thread do OS (~1MB stack)Reutiliza threads do pool
CustoAlto β€” criacao/destruicao carasBaixo β€” pool gerencia lifecycle
ComposicaoRuim β€” sem await/continuacoesExcelente β€” async/await nativo
CancelamentoManual (flags, Abort depreciado)CancellationToken nativo
Quando usarSTA, afinidade de CPU, loops dedicadosCPU-bound, I/O-bound, tudo mais
// Prefer Task for CPU-bound parallelism Task t = Task.Run(() => DoCpuWork()); // Raw Thread only if you need OS thread control var thread = new Thread(() => DoCpuWork()) { IsBackground = true }; thread.Start(); // Task uses the thread pool and composes well with async/await. // Use Thread for special cases: STA, CPU affinity, long-lived dedicated loops.

Fluxo de sincronizacao

acquireacquireentersblocksexitunblockThread 1Thread 2lock(obj)Critical SectionWaitingReleased

Blocking vs Async I/O

.Result e .Wait() bloqueiam uma thread enquanto esperam. Em ASP.NET isso desperdicar threads do pool e pode causar thread starvation.
// BAD: Blocks a thread while waiting string s = httpClient.GetStringAsync(url).Result; // GOOD: Asynchronous, no thread blocked during I/O string s2 = await httpClient.GetStringAsync(url); // Blocking wastes a thread; prefer await for I/O.
Por que preferir Task.Run() a new Thread()?
Task.Run() usa o ThreadPool, que reutiliza threads ja existentes β€” sem custo de criacao/destruicao do OS. Alem disso, Task compoe com async/await, suporta CancellationToken, e propaga excecoes de forma estruturada. Thread bruto so faz sentido para cenarios especiais como threads STA ou loops de longa duracao dedicados.