Un bloqueig reentrant, també anomenat mutex reentrant o bloqueig recursiu, és un mecanisme de sincronització en programació concurrent que permet que un mateix fil d'execució adquireixi diverses vegades un bloqueig que ja posseeix sense quedar-se bloquejat a si mateix. Aquesta propietat el diferencia d’un bloqueig ordinari o no reentrant, en què un segon intent d’adquisició per part del mateix fil pot provocar un interbloqueig.
El terme anglès habitual és reentrant lock o reentrant mutex. En l’àmbit de la informàtica, el diccionari anglès-català de Softcatalà recull lock com a bloqueig o blocatge, de manera que la denominació bloqueig reentrant és coherent amb aquesta equivalència terminològica.
Funcionament Un bloqueig reentrant manté habitualment dues dades internes: la identitat del fil que el posseeix i un comptador del nombre de vegades que aquest fil l’ha adquirit. Quan un fil adquireix el bloqueig per primera vegada, passa a ser-ne el propietari i el comptador s’inicialitza. Si el mateix fil torna a adquirir-lo abans d’alliberar-lo, l’operació té èxit i el comptador augmenta.
Perquè el bloqueig quedi completament alliberat i un altre fil el pugui obtenir, el propietari l’ha d’alliberar el mateix nombre de vegades que l’ha adquirit. Si un fil diferent intenta obtenir el bloqueig mentre encara és propietat d’un altre, queda bloquejat o ha d’esperar fins que el recurs estigui disponible.
Diferència respecte d’un bloqueig no reentrant En un bloqueig no reentrant, si el mateix fil intenta adquirir dues vegades el mateix recurs sense haver-lo alliberat, pot quedar esperant indefinidament. Això pot passar, per exemple, quan una funció protegida per un bloqueig crida una altra funció que també necessita accedir al mateix recurs protegit.
En canvi, un bloqueig reentrant permet aquesta adquisició repetida per part del fil propietari. Per això és útil en estructures de codi amb crides imbricades, mètodes que es criden entre si o funcions recursives. Tot i així, el bloqueig continua impedint que altres fils accedeixin simultàniament al recurs compartit.
Ús en llenguatges i biblioteques Diversos entorns de programació ofereixen implementacions de bloquejos reentrants. A Python, el mòdul `threading` proporciona `RLock`, un objecte de bloqueig reentrant que pot ser adquirit múltiples vegades pel mateix fil, sempre que sigui alliberat després el mateix nombre de vegades.
En sistemes compatibles amb POSIX, els mutexos de tipus `PTHREAD_MUTEX_RECURSIVE` tenen un comportament equivalent: el mateix fil pot tornar a bloquejar el mutex sense provocar un interbloqueig, mentre que la seva alliberació completa requereix tantes operacions de desbloqueig com adquisicions s’hagin fet.
Avantatges i limitacions Els bloquejos reentrants poden evitar interbloquejos causats per l’autoadquisició accidental d’un mateix bloqueig. També faciliten l’adaptació de codi complex o de components que comparteixen una mateixa protecció interna.
Tanmateix, no eliminen els problemes generals de sincronització. Un ús excessiu pot amagar dependències poc clares entre funcions o fer més difícil raonar sobre l’ordre d’adquisició dels bloquejos. A més, com passa amb altres mecanismes d’exclusió mútua, continuen existint riscos d’interbloqueig si diversos fils adquireixen diferents bloquejos en ordres incompatibles.
El llibre Python Concurrency with Asyncio, de Matthew Fowler, tracta els bloquejos reentrants dins del context de la concurrència multifil i els presenta com una eina per evitar determinades formes d’interbloqueig quan un fil torna a entrar en codi protegit pel mateix mecanisme de sincronització.Fowler, Matthew. Python Concurrency with Asyncio. Manning Publications, 2022, capítol 7.
Vegeu també Cadenat (informàtica) Exclusió mútua Interbloqueig Fil d'execució Programació concurrent
Referències
Categoria:Patrons de disseny de programari