stringtranslate.com

Mutex reentrante

En informática , el mutex reentrante ( mutex recursivo , bloqueo recursivo ) es un tipo particular de dispositivo de exclusión mutua (mutex) que puede bloquearse varias veces por el mismo proceso/hilo , sin causar un bloqueo .

Mientras que cualquier intento de realizar la operación de "bloqueo" en un mutex ordinario (bloqueo) fallaría o se bloquearía cuando el mutex ya está bloqueado, en un mutex recursivo esta operación tendrá éxito si y solo si el hilo que bloquea es el que ya tiene el bloqueo. Por lo general, un mutex recursivo rastrea la cantidad de veces que se ha bloqueado y requiere que se realicen la misma cantidad de operaciones de desbloqueo antes de que otros hilos puedan bloquearlo.

Motivación

Los mutex recursivos resuelven el problema de no reentrada con mutex regulares: si una función que toma un bloqueo y ejecuta una devolución de llamada es llamada por la devolución de llamada, se produce un bloqueo . [1] En pseudocódigo , esa es la siguiente situación:

var m : Mutex // Un mutex no recursivo, inicialmente desbloqueado.función bloquear_y_llamar(i : entero) m.bloqueo() devolución de llamada(i) m.desbloquear()función callback(i : Integer) si i > 0 bloquear_y_llamar(i - 1)lock_and_call(1) // Invocando la función

Dadas estas definiciones, la llamada a la función lock_and_call(1) provocará la siguiente secuencia de eventos:

Reemplazar el mutex por uno recursivo resuelve el problema, porque el m.lock() final tendrá éxito sin bloquearse.

Uso práctico

W. Richard Stevens señala que los bloqueos recursivos son "difíciles" de usar correctamente y recomienda su uso para adaptar código de un solo subproceso sin cambiar las API , pero "solo cuando no es posible otra solución". [2]

El mecanismo de sincronización nativo del lenguaje Java , monitor , utiliza bloqueos recursivos. Sintácticamente, un bloqueo es un bloque de código con la palabra clave 'synchronized' precediéndolo y cualquier referencia a Object entre paréntesis que se usará como mutex. Dentro del bloque sincronizado, el objeto dado se puede usar como una variable de condición haciendo un wait(), notify() o notifyAll() sobre él. Por lo tanto, todos los Objects son mutex recursivos y variables de condición . [3]

Ejemplo

  1. El hilo A llama a la función F, que adquiere un bloqueo reentrante para sí misma antes de continuar.
  2. El hilo B llama a la función F, que intenta adquirir un bloqueo reentrante para sí misma, pero no puede hacerlo debido a que ya hay uno pendiente, lo que da como resultado un bloqueo (espera) o un tiempo de espera si se lo solicita.
  3. El hilo F del subproceso A se llama a sí mismo recursivamente. Ya posee el bloqueo, por lo que no se bloqueará a sí mismo (no se producirá un bloqueo). Esta es la idea central de un mutex reentrante y es lo que lo diferencia de un bloqueo normal.
  4. El hilo F del subproceso B todavía está esperando, o ha detectado el tiempo de espera y lo ha solucionado.
  5. El hilo F del hilo A termina y libera su(s) bloqueo(s)
  6. El hilo F del subproceso B ahora puede adquirir un bloqueo reentrante y continuar si todavía estaba esperando

Emulación de software

La emulación de software se puede lograr [ aclaración necesaria ] utilizando la siguiente estructura: [ cita necesaria ]

Adquisición

  1. Adquirir la condición de control.
  2. Si se establece el propietario y no el hilo actual, espere a que se notifique la condición de control (esto también libera la condición).
  3. Establezca el propietario en el hilo actual. El identificador del propietario ya debería haberse borrado en este punto, a menos que el adquirente ya sea el propietario.
  4. Incrementar el recuento de adquisiciones (siempre debería resultar en 1 para nuevos propietarios).
  5. Liberar la condición de control.

Liberar

  1. Adquirir la condición de control, afirmando que el propietario es el liberador.
  2. Disminuye el recuento de adquisiciones, afirmando que el recuento es mayor o igual a cero.
  3. Si el recuento de adquisiciones es cero, borre la información del propietario y notifique la condición de control.
  4. Liberar la condición de control.

Referencias

  1. ^ Buschmann, Frank; Henney, Kevlin; Schmidt, Douglas C. (2007). Arquitectura de software orientada a patrones, un lenguaje de patrones para computación distribuida. John Wiley & Sons. pág. 374. ISBN 9780470065303.
  2. ^ Stevens, W. Richard; Rago, Stephen A. (2013). Programación avanzada en el entorno UNIX . Addison-Wesley. pág. 434.
  3. ^ David Hovemeyer. "Conferencia 17: subprocesos de Java, sincronización". CS 365 - Computación paralela y distribuida . Consultado el 4 de junio de 2015 . {{cite book}}: |work=ignorado ( ayuda )