lezione 08

concorrenza e multithreading

thread, mutex e async in c++ moderno.

livello: intermedio durata: 40 min output: worker pool badge: concurrency advanced

perché concorrente

la concorrenza permette di sfruttare più core e ridurre la latenza. va gestita con disciplina.

misura prima di parallelizzare: più thread non sempre significa più performance.

thread base

usa std::thread per eseguire una funzione in parallelo.

#include <thread>
#include <iostream>

void job() {
    std::cout << "task";
}

int main() {
    std::thread t(job);
    t.join();
}

mutex e lock

proteggi le risorse condivise con std::mutex e std::lock_guard.

#include <mutex>

std::mutex m;
int counter = 0;

void safe_inc() {
    std::lock_guard<std::mutex> guard(m);
    counter++;
}

async e future

std::async semplifica task asincroni con std::future.

#include <future>

int calc() { return 21 * 2; }

int main() {
    auto fut = std::async(std::launch::async, calc);
    int result = fut.get();
}

errori comuni

  • dimenticare join() o detach()
  • data race su variabili globali
  • deadlock per ordine di lock sbagliato
  • usare shared_ptr senza sincronizzazione

esercizi

crea un contatore thread-safe con std::atomic e confronta con il mutex.

implementa una coda di job con due thread consumer.

checklist

  • usa lock_guard per lock sicuri
  • preferisci async per task semplici
  • evita state condiviso quando puoi
  • scrivi test di concorrenza

panoramica

In questo capitolo su concorrenza e multithreading, thread, mutex e async in c++ moderno. L'obiettivo è trasformare i concetti in micro-pattern riutilizzabili con esempi piccoli e verificabili.

Lavora in sequenza: leggi, prova, modifica gli snippet e annota i trade-off principali (performance, leggibilità, manutenzione).

badge: concurrency advanced

obiettivi

  • capire e applicare perché concorrente in uno scenario reale
  • capire e applicare thread base in uno scenario reale
  • capire e applicare mutex e lock in uno scenario reale
  • capire e applicare async e future in uno scenario reale

scheda rapida

#include <iostream>
#include <vector>

int main() {
  std::vector<int> dati{1, 2, 3};
  for (auto &v : dati) {
    v *= 2;
  }
  for (const auto &v : dati) {
    std::cout << v << " ";
  }
  std::cout << "\n";
  return 0;
}

Adatta questo scheletro agli esempi della lezione e sostituisci i dati con il tuo dominio.

tips

  • compila con warning elevati
  • preferisci RAII
  • usa const ovunque possibile
  • usa condition_variable per sincronizzazione
  • preferisci future per risultati
  • gestisci shutdown pulito

tip: La sincronizzazione esplicita vale più di mille spin loop.

mini progetto

Queue producer/consumer con condition_variable.

  • implementa coda protetta
  • crea producer e consumer
  • notifica con condition_variable
  • gestisci stop

output atteso: uno script o query ripetibile con risultati verificabili.

start a brief