Come la maggior parte dei
programmatori, sono cosciente dei rischi nei quali si incorre in un ambiente
multithreading. Per me come per altri del mestiere, termini come race-condition,
concurrency, e deadlock, sono pane quotidiano. So ad esempio che in buon
senso consiglia che un lock() duri il meno possibile per evitare che
altri thread concorrenti rimangano bloccati in attesa e si verifichi un degrado
delle prestazioni.
Mai però mi sarei aspettato di averne la prova nel
mondo "reale", proprio sulla mia pelle. Mi spiego: stamane sono stato in posta,
per ritirare un pacco che veniva da Amazon e mi sono imbattuto nel nuovissimo e
fiammante sistema di gestione delle code. Bello e molto ben fatto. Una
macchinetta riceve gli utenti all'ingresso e solerte gli fornisce un numerello
che poi "prima o poi" appare sul display che sovrasta ogni sportello.
Il problema sta proprio nel "prima o poi". Chiunque
ha ben presente la vecchina che si presenta allo sportello per fare un vaglia;
si mette in coda, arriva il suo turno, l'impiegato si accorge che la vecchina
non ha compilato il modulo quindi gli spiega in due parole come si compila e poi
passa all'utente successivo, mentre il "thread-vecchina" compila il
modulo.
Il nuovo sistema invece fa sì che l'utente ponga un
lock esclusivo sullo sportello, perciò tutti "thread-utente" rimangono
inutilmente in attesa che il "thread-vecchina" compili il modulo mentre
il "thread-impiegato-dello-sportello" la guarda senza fare
nulla.
lock(
sportello )
{
Modulo vaglia =
impiegato.ConsegnaModulo();
impiegato.AttendiEConversaConLoSportelloAdiacente();
while( !vaglia.IsCorretto
)
vecchina.Compila( vaglia
);
impiegato.EseguiVaglia();
impiegato.AttendiEConversaConLoSportelloAdiacente();
vecchina.ContaISoldi();
Pagamento pag =
impiegato.RiceviContanteDa( vecchina );
impiegato.AttendiEConversaConLoSportelloAdiacente();
Ricevuta ric =
vecchina.RitiraRicevutaDa( impiegato );
impiegato.SalutaAmabilmenteLaVecchina();
}
Vi lascio immaginare che genere di attività svolgono
nel frattempo i "thread-utente" in attesa. (utente.Impreca() è molto
gettonato). Comunque questo dimostra quanto una pessima politica di gestione
della concorrenza possa impattare sulle performance di un'attività.
10 persone in coda = 1 ora
abbondante.