Multithreading em C++
Sistemas concorrentes de máxima perfomance com controle total sobre recursos. C++ oferece controle total sobre threads, memória e sincronização. Sua experiência define os limites, não o compilador
RecursosRecursos de Threading
std::thread
Criação básica de threads e gerenciamento com controle total sobre o ciclo de vida e execução. Permite iniciar tarefas em paralelo, controlar quando começam e terminam, e coordenar a execução de diferentes partes de um programa. Com std::thread, é possível criar aplicações mais responsivas e aproveitar melhor processadores com múltiplos núcleos.
std::async
Permite executar funções em segundo plano sem precisar gerenciar explicitamente threads, simplificando o código e reduzindo a possibilidade de erros. Ao utilizar std::async, é possível obter resultados de forma assíncrona por meio de objetos std::future, garantindo que o processamento pesado não bloqueie a execução principal do programa. É ideal para operações independentes que podem ser processadas em paralelo.
Sincronização
Mutexes, variáveis de condição e operações atômicas para programação thread-safe. A sincronização é essencial quando múltiplas threads acessam e modificam os mesmos recursos. Com ferramentas como std::mutex, std::condition_variable e operações atômicas (std::atomic), é possível coordenar o acesso, evitando conflitos e garantindo a integridade dos dados.
std::jthread
Uma versão melhorada no C++20 com limpeza automática e cancelamento cooperativo. std::jthread facilita o gerenciamento de threads ao encerrar automaticamente sua execução no destrutor, evitando esquecimentos e vazamentos de recursos. Além disso, oferece suporte integrado para cancelamento cooperativo por meio de std::stop_token, permitindo que threads sejam interrompidas de forma segura e previsível.Essa abordagem reduz a complexidade do código e torna a programação concorrente mais robusta e menos propensa a erros.
Corrotinas
Corrotinas do C++20 para multitarefa cooperativa leve e programação assíncrona. As corrotinas permitem pausar e retomar funções em pontos específicos, possibilitando a escrita de código assíncrono de forma mais clara e linear. Com o C++20, a linguagem oferece suporte nativo a esse recurso, facilitando a criação de pipelines de processamento, geradores de dados e sistemas de multitarefa leve. Diferente das threads tradicionais, corrotinas não exigem troca de contexto no nível do sistema operacional, tornando sua execução mais rápida e com menor consumo de recursos.
Thread Pools
Gerenciamento eficiente de recursos com worker threads reutilizáveis para melhor performance. Um thread pool é um conjunto de threads previamente criadas que permanecem disponíveis para executar múltiplas tarefas ao longo da vida útil do programa. Em vez de criar e destruir threads para cada operação , o thread pool reutiliza as mesmas threads, reduzindo a sobrecarga e melhorando a eficiência. Essa abordagem é ideal para aplicações que processam um grande número de tarefas curtas ou de média duração, garantindo melhor uso dos recursos do sistema e maior previsibilidade na execução.
Alguns Exemplos de Código
#include <thread>
#include <iostream>
using namespace trabalhador(int id) {
std::cout << "Thread " << id << " trabalhando\n";
}
int main() {
std::thread t1(trabalhador, 1);
std::thread t2(trabalhador, 2);
t1.join();
t2.join();
return 0;
}
Operações Assíncronas
#include <chrono>
#include <future>
#include <iostream>
using namespace std;
int returnTwo() { return 2; }
int main()
{
// Criando um objeto futuro e a thread que executa
// A função retorna dois de forma assíncrona
future<int> f = async(launch::async, returnTwo);
// Pegando e printando o resultado
cout << f.get();
return 0;
}
jthread Moderno (C++20)
#include <iostream>
#include <thread>
#include <stop_token>
void foo(std::stop_token stoken) {
// Função que será executada na thread, recebe um token para saber quando parar
while (!stoken.stop_requested()) {
std::cout << "Running\n";
std::this_thread::sleep_for(std::chrono::seconds(1)); // Espera 1 segundo
}
}
int main() {
std::jthread t(foo); // Cria uma jthread que executa a função foo, passando automaticamente o stop_token
std::this_thread::sleep_for(std::chrono::seconds(5));
t.request_stop();
t.join(); // Aguarda a thread foo finalizar antes de continuar
return 0;
}
Comparação Entre Linguagens
Recurso | C++ | Go | Rust | Elixir |
---|---|---|---|---|
Tarefas Leves | Não (threads do SO) | Sim (goroutines) | Não (threads do SO) | Sim (processos) |
Segurança de Memória | Manual | GC + Manual | Compile-time | Runtime |
Performance | Máxima | Alta | Máxima | Boa |
Modelo de Concorrência | Memória Compartilhada | CSP (Canais) | Ownership | Modelo Actor |