Concorrência e Multithreading em C++: Guia Completo

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução à concorrência e multithreading em C++



Aplicações modernas exigem desempenho máximo. Concorrência e multithreading em C++ permitem usar eficientemente processadores multi-core, acelerando a execução de tarefas. Sem entender esses conceitos, é impossível criar sistemas de alta carga, processadores de dados ou motores de jogos.



Neste artigo, vamos analisar os principais mecanismos de multithreading em C++, começando com o básico std::thread e terminando com padrões avançados. Você aprenderá como evitar condições de corrida, sincronizar threads corretamente e escrever código paralelo seguro.



Fundamentos do multithreading: std::thread e std::jthread



A classe std::thread (C++11) é a base da programação multithread. Ela permite executar uma função ou objeto callable em uma thread separada. Vejamos um exemplo simples:



#include <iostream>#include <thread>

void worker(int id) { std::cout << "Thread " << id << " iniciou o trabalho"; std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "Thread " << id << " finalizada";}

int main() { std::thread t1(worker, 1); std::thread t2(worker, 2); t1.join(); t2.join(); return 0;}


Pontos-chave:

  • join() — a thread principal espera a thread filha terminar
  • detach() — a thread continua executando independentemente (risco de vazamento de recursos)
  • std::jthread (C++20) — chama automaticamente join() no destrutor


Sempre verifique joinable() antes de chamar join() para evitar junção dupla.



Sincronização de threads: mutexes e locks



O principal problema do multithreading são as condições de corrida, quando várias threads modificam simultaneamente uma variável compartilhada. Para proteção, usamos mutexes.



std::mutex e std::lock_guard



#include <iostream>#include <thread>#include <mutex>

std::mutex mtx;int counter = 0;

void increment() { for (int i = 0; i < 100000; ++i) { std::lock_guard<std::mutex> lock(mtx); ++counter; }}

int main() { std::thread t1(increment); std::thread t2(increment); t1.join(); t2.join(); std::cout << "Resultado: " << counter << ""; // 200000 return 0;}


std::lock_guard libera automaticamente o mutex ao sair do escopo. Para controle mais flexível, use std::unique_lock.



Deadlock e std::scoped_lock



Deadlock ocorre quando duas threads esperam uma pela outra. A solução é usar std::scoped_lock (C++17), que captura vários mutexes atomicamente:



std::mutex m1, m2;

void safe_function() { std::scoped_lock lock(m1, m2); // trabalho seguro com dois recursos}


Algoritmos paralelos e std::async



Para executar tarefas assíncronas sem gerenciamento manual de threads, use std::async. Ele retorna um std::future, do qual você pode obter o resultado.



#include <iostream>#include <future>#include <chrono>

int compute(int n) { std::this_thread::sleep_for(std::chrono::seconds(n)); return n * n;}

int main() { auto future1 = std::async(std::launch::async, compute, 2); auto future2 = std::async(std::launch::async, compute, 3); std::cout << "Resultados: " << future1.get() << ", " << future2.get() << ""; // 4, 9 return 0;}


Políticas de lançamento:

  • std::launch::async — execução em uma nova thread
  • std::launch::deferred — execução adiada (lazy)

Blogs

Book Recommendations