Programmazione multithread senza lock con STM.NET

Microsoft ha da poco rilasciato una versione “sperimentale” del .NET Framework che implementa un sistema per le transazioni in memoria (STM.NET). A prima vista potrebbe sembrare qualcosa che ha a che fare con la possibilità di implementare il concetto di transazione (che siamo abituati a vedere in un database relazionale) per la manipolazione di dati in memoria, e infatti questa è una delle funzionalità disponibili. Ma l’aspetto importante di questo approccio è che può essere usato per scrivere programmi che sfruttano la disponibilità di più core senza ricorrere a tecniche di lock nell’accesso a dati condivisi.

L’idea è quella di consentire al JIT di “comprendere” quali sono gli accessi a rischio di race condition e di isolarli all’interno di transazioni che vengono “protette” con tecniche che possono rieseguire il codice e isolare l’effetto di una operazione interrotta da un accesso concorrente (proprio perché si usa il concetto di transazione, né più né meno di come si fa con un database).

Se non avete voglia di installare questa versione del framework in una macchina virtuale (non mischiatela con la Beta di Visual Studio 2010!!), vi raccomando di dare una lettura alla Programming Guide che descrive le caratteristiche di questa tecnologia (assolutamente sperimentale, non ottimizzata, non supportata, ecc. ecc.) e che a pagina 66 mostra alcune misure prestazionali che promettono una scalabilità molto maggiore del codice scritto usando questa tecnica. Il break-even si raggiunge con 4 thread (eseguiti su 4 core), i guadagni cominciano a essere evidenti con 6 core e (cosa più importante) la curva cresce in maniera quasi lineare all’aumentare dei core (al contrario delle tecniche basate sui lock dove l’aumento dei thread non fa altro che diminuire il throughput complessivo). Seguono molti altri grafici e commenti alle differenti prestazioni ottenibili con diverse tecniche, ma il punto è assolutamente chiaro: siamo in una fase di completa transizione, l’era del multi-core è appena cominciata e con 2, 4 e forse anche 8 core su un desktop si ottiene qualche miglioramento prestazionale con il software attuale, ma guardando oltre, da qui a 5/10 anni, il codice scritto oggi è assolutamente inadeguato a sfruttare i miglioramenti prestazionali che saranno disponibili con numeri più alti di core sulla macchina.

Considerato l’impatto che queste tecniche di programmazione hanno, non è assolutamente prematuro preoccuparsi oggi di questa necessità (almeno dal punto di vista degli strumenti di base, sistemi operativi, framework e compilatori) visti i tempi necessari perché una tecnologia simile sia affinate e resa disponibile in produzione. Ovviamente questi costrutti, che mirano ad aumentare il livello di astrazione nel codice di un programma che affronta situazioni di concorrenza multi-thread, dovranno diventare parti integranti dei linguaggi di programmazione. L’aspetto più complesso è probabilmente la necessità di cambiare mentalità e di riuscire a descrivere il problema in termini più astratti, pensando meno al dettaglio implementativo – cosa non facile per chi oggi è abituato a pensare in termini di lock sui singoli oggetti.