Mètodes

42 (VIII): philosophers, fils a taula

Filòsofs que mengen, pensen i moren de fam: concurrència, mutex i deadlocks explicats amb espaguetis.

42 (VIII): philosophers, fils a taula

so_long tenia finestra i sprites; philosophers no té res a la vista: un terminal que imprimeix línies i, si ho fas malament, un programa que es penja o declara morts que estan vius. És el problema clàssic dels filòsofs a taula: N filòsofs al voltant d’una taula circular, un tenidor entre cada parella, i per menjar calen els dos de costat. Si un no menja dins del temps donat, mor, i el log ho ha de dir sense barrejar línies ni afegir res després.

El problema de veritat

Aquí no s’ordenen dades: es coordinen fils. El perill té tres cares. El deadlock: si tots els filòsofs agafen primer el tenidor esquerre, tots queden esperant el dret per sempre. Les condicions de carrera: el moment de l’últim àpat l’escriu un fil i el llegeix un altre; sense protecció, de tant en tant algú mor per error o sobreviu sent mort. I la precisió temporal: usleep no dorm el que li demanes, i mig mil·lisegon de desfase és la diferència entre un filòsof viu i un mort.

Com ho vaig resoldre

Un fil per filòsof i un mutex per tenidor. Contra el deadlock, trencar el cicle: els filòsofs parells agafen primer el tenidor dret i els senars primer l’esquerre; així ningú queda bloquejat en cercle. Contra les carreres, estat compartit mínim i protegit: el flag de parada i el log tenen el seu mutex, i cada filòsof protegeix el seu moment d’últim àpat i el comptador de menjars amb un mutex propi. Un monitor al fil principal recorre la taula cada mig mil·lisegon comprovant si algú ha superat el temps o si tots han menjat el que tocava, i quan toca aturar-ho tot, ho atura. Per dormir amb precisió vaig fer un sleep a trossos petits que comprova la parada, i un desfase inicial entre parells i senars perquè no arrenquin tots alhora amb la mateixa gana. El cas d’un sol filòsof, amb un únic tenidor, va per camí propi: l’agafa, el log ho diu, i mor.

Una curiositat: tinc dos repositoris d’aquest projecte, philosophers i 42_philosophers. El primer funcionava, però el vaig repetir amb l’estructura més neta que havia anat aprenent; comparar-los és veure com havia canviat la meva manera de partir un problema.

Què m’enduc

Philosophers em va deixar una desconfiança sana: el bug de concurrència no surt cada vegada, surt un de cada cinquanta execucions, així que vaig acabar provant el programa en bucles de centenars d’execucions abans de dir que anava bé. També vaig entendre que un mutex no és màgia sinó disciplina: saber exactament quines dades toca qui i protegir només allò que cal. I que els problemes clàssics dels anys seixanta i setanta continuen ensenyant coses que cap tutorial modern explica tan bé.