L'algoritmo del fornaio è uno dei metodi di mutua esclusione che trovano applicazione pratica nella programmazione parallela per serializzare l'esecuzione delle sezioni critiche da parte di più processi o thread concorrenti.

L'algoritmo deve il nome al suo inventore Leslie Lamport, che propose l'analogia con il modello reale di una frequentata panetteria, dove i clienti strappano un numero prima di mettersi in fila ad aspettare il proprio turno. I clienti del fornaio rappresentano i task in attesa del proprio turno per eseguire la sezione critica.

Schema

modifica

Quella che segue è una descrizione schematica dell'algoritmo in pseudocodice C++:

// dichiarazione delle variabili globali comuni
bool sceglie[N] = {false}; // N costante
int numero[N] = {0};

int i; // indice del thread in esecuzione
// ...
for (;;) {
    sceglie[i] = true;
    numero[i] = 1 + max(numero[0], numero[1], ..., numero[N - 1]);
    sceglie[i] = false;
    for (j = 0; j < N; ++j) {
        while (sceglie[j]);
        while (
            (numero[j] != 0) &&
            (
             (numero[j] < numero[i]) ||
             ((numero[j] == numero[i]) && (j < i))
            )
        );
    }
    // <sezione critica>
    numero[i] = 0;
    // <sezione non critica>
}

Funzionamento

modifica

Al di là di ogni affinità con le situazioni reali, è possibile che più thread ricevano lo stesso numero di turno. Per ovviare a questa circostanza si introduce l'indice del thread come secondo argomento di confronto. Se più thread ricevono lo stesso numero di turno, si conviene di assegnare la precedenza al thread con l'indice più basso. Va notato che l'indice di ciascun thread deve essere unico: esso può venire assegnato al momento della creazione o passato come parametro. Nell'esempio schematico riportato sopra, la costante N rappresenta il numero massimo di thread concorrenti. Dopo aver ricevuto il suo indice unico, ogni thread scrive solo nelle sue slot (sceglie[i] e numero[i]). La serializzazione è assicurata dalle due iterazioni while consecutive. Questi cicli vengono ripetuti da ogni thread per tutti i thread, incluso quello in esecuzione e i thread non attivi. Solo quando non ci sono più altri thread con priorità più alta è possibile l'accesso alla sezione critica.

Considerazioni

modifica

L'algoritmo del fornaio garantisce che un solo thread alla volta possa accedere alla sezione critica, indipendentemente dall'ordine delle commutazioni di contesto e dagli altri dettagli dello scheduling. Sussiste tuttavia il principale inconveniente che è proprio di tutti gli algoritmi di coordinazione decentrata, cioè non coordinata dallo scheduler: i task in attesa continuano ad utilizzare il processore in un ciclo di attesa attiva detto busy waiting, rallentando così gli altri thread nel sistema.

Bibliografia

modifica

Voci correlate

modifica
  Portale Informatica: accedi alle voci di Wikipedia che trattano di informatica

📚 Artikel Terkait di Wikipedia

Algoritmo di Dekker

Consultato il 7 gennaio 2010 E. W. Dijkstra - Solution of a Problem in Concurrent Programming Control - Communications of the ACM - September 1965 - page 569

Metodologia agile

down chart Concurrent Versions System Context Driven Testing Crystal (informatica) Dynamic Systems Development Method Extreme programming Feature Driven

Ergo Proxy

maggio 2011. ^ (EN) G4 Canada continues exclusive anime programming with six new concurrent series, su G4 Canada, 25 giugno 2007. URL consultato il 21

Elixir (linguaggio di programmazione)

Leanpub, 12 maggio 2015, p. 53. (EN) Dave Thomas, Programming Elixir: : Functional > Concurrent > Pragmatic > Fun, Prima edizione, The Pragmatic Bookshelf

ChucK

consultato il 17 gennaio 2021. ^ ChucK : Strongly-timed, Concurrent, and On-the-fly Music Programming Language, su chuck.cs.princeton.edu. URL consultato il

Model checking

verification of finite state concurrent systems using temporal logic, E.M. Clarke, E.A. Emerson, and A.P. Sistla, ACM Trans. on Programming Languages and Systems

Future (informatica)

libreria concurrent.futures e da 3.5 con async e await) e molti altri. ^ (EN) Daniel Friedman e David Wise, The Impact of Applicative Programming on Multiprocessing

Programmazione a vincoli

imposti. La programmazione a vincoli temporal concurrent (TCC) e la programmazione a vincoli temporal concurrent non-deterministica (NTCC) sono varianti della