Programmazione concorrente in POSIX C
Pagina 1 di 5
Tutti i moderni sistemi operativi adottano da anni un modello di gestione multi-processo, assegnando tempi di esecuzione e spazio di memoria ai vari programmi attivi contemporaneamente. Negli ultimi tempi, soprattuto grazie alla pervasività delle comunicazioni via rete, questo concetto è stato ampliato al singolo software, suddividendo un medesimo processo in molteplici flussi di controllo detti threads. Questo nuovo approccio apporta enormi cambiamenti alla struttura di un software, sia a livello teorico sia a livello pratico; come sempre accade, la modularità e l'espressività si pagano in termini di aumento della complessità del software.
I linguaggi di programmazione più recenti, a partire da Java, offrono tutti API native per la creazione e la gestione dei threads; i sistemi basati su virtual machine quali Java e C# presentano allo sviluppatore un livello di astrazione uniforme su questa tematica mentre tutti gli altri devono affidarsi alle primitive del sistema operativo in uso, spesso incorrendo in problematiche di portabilità del codice. In questo contesto si inseriscono le librerie POSIX Thread (PThread) per permettere anche agli sviluppatori C una minima garanzia di portabilità tra i diversi sistemi.
Prerequisiti
Questo articolo è rivolto a tutti coloro che vogliano approcciare il tema della programmazione concorrente in linguaggi a basso livello. In questa presentazione si presuppone che il lettore abbia precedentemente maturato una minima conoscenza del linguaggio C in quanto non saranno trattati argomenti di base quali, ad esempio, la gestione della memoria e i tipi di dato.
Le librerie POSIX Thread
Come facilmente intuibile dal nome, le librerie POSIX Thread sono parte dell'insieme di standard POSIX (Portable Operating System Interface [for Unix]). Citandone la definizione "PThread [...] specifies a set of interfaces (functions, header files) for threaded programming [...] a single process can contain multiple threads, all of which are executing the same program [...] share the same global memory (data and heap segments), but each thread has its own stack". Questo estratto descrive esattamente cosa implichi la programmazione multi-threads in ambiente POSIX:
- più flussi di controllo (threads) in un singolo processo;
- condivisione della memoria contenente il codice (data segment) e della memoria dinamica (heap segment);
- stack privato.
Utilizzare lo standard POSIX garantisce un alto livello di compatibilità tra tutti i sistemi POSIX-compliant quali, ad esempio, GNU/Linux, Mac OSX, BSD e anche Microsoft Windows (con alcune integrazioni). Durante questo articolo faremo riferimento all'uso del compilatore GCC in ambiente GNU/Linux; ovviamente tutte le considerazioni sono riportabili a qualunque altro ambiente POSIX-like.
Un primo (erroneo) esempio
La libreria pthread.h mette a disposizione tutto l'occorrente per la programmazione in ambiente multi-threads; piuttosto che fare una mera elencazione delle primitive fornite, presenteremo un esempio pratico discutendone di volta in volta le peculiarità.
Consideriamo dunque il seguente problema: il programma bancario bank deve leggere da vari files delle operazioni di prelievo e/o deposito da effettuare su un conto; tali files avranno dunque la seguente forma:
+120 -550 +896 +5541 -85 ...Per velocizzare le operazioni diversi threads "cassiere" operano ciascuno su un singolo files e aggiornano concorrentemente il conto del cliente; eseguite tutte le operazioni avremo in output lo stato del conto.







