vista usar threads son relación que programacion programa procesos proceso mapa los lock hilos español entre diferencia cuál cuando cuadro comparativo multithreading thread-safety reentrancy

multithreading - usar - Código de reentrada vs. seguridad de subprocesos



que son los hilos en programacion (2)

Ese artículo dice:

"una función puede ser reentrante, hilo seguro, ambos, o ninguno".

También dice:

"Las funciones sin reentrada no son seguras para el hilo".

Puedo ver cómo esto puede causar confusión. Significan que las funciones estándar documentadas como no necesarias para ser reentrantes tampoco son necesarias para ser seguras para subprocesos, lo cual es cierto para las bibliotecas POSIX iirc (y POSIX declara que también es cierto para las bibliotecas ANSI / ISO, teniendo ISO ningún concepto de hilos y, por lo tanto, ningún concepto de seguridad de hilos). En otras palabras, "si una función dice que no es reentrante, entonces está diciendo que también es inseguro para el hilo". Esa no es una necesidad lógica, es solo una convención.

Aquí hay un pseudo-código que es seguro para subprocesos (bueno, hay muchas oportunidades para que las devoluciones de llamadas creen puntos muertos debido a la inversión de bloqueo, pero supongamos que la documentación contiene información suficiente para que los usuarios eviten eso) pero no reentrantes. Se supone que incrementa el contador global y realiza la devolución de llamada:

take_global_lock(); int i = get_global_counter(); do_callback(i); set_global_counter(i+1); release_global_lock();

Si la devolución de llamada vuelve a llamar a esta rutina, lo que da como resultado otra devolución de llamada, ambos niveles de devolución de llamada obtendrán el mismo parámetro (lo que podría estar bien, dependiendo de la API), pero el contador solo se incrementará una vez (lo cual es casi seguro que no API que desea, por lo que debería estar prohibida).

Eso supone que el bloqueo es recursivo, por supuesto. Si el bloqueo no es recursivo, entonces, por supuesto, el código no es reentrante de todos modos, ya que tomar el bloqueo la segunda vez no funcionará.

Aquí hay un pseudo-código que es "débilmente reentrante" pero no es seguro para subprocesos:

int i = get_global_counter(); do_callback(i); set_global_counter(get_global_counter()+1);

Ahora está bien llamar a la función desde la devolución de llamada, pero no es seguro llamar a la función simultáneamente desde diferentes subprocesos. Tampoco es seguro llamarlo desde un manejador de señal, porque la reentrada de un manejador de señal podría también romper el conteo si la señal sucediera en el momento correcto. Entonces el código no entra por la definición correcta.

Aquí hay un código que podría decirse que es completamente reentrante (excepto que creo que el estándar distingue entre reentrantes y ''no interrumpible por señales'', y no estoy seguro de dónde se produce), pero aún no es seguro para subprocesos:

int i = get_global_counter(); do_callback(i); disable_signals(); // and any other kind of interrupts on your system set_global_counter(get_global_counter()+1); restore_signal_state();

En una aplicación de subproceso único, esto está bien, suponiendo que el sistema operativo admite la desactivación de todo lo que se debe deshabilitar. Impide que la reentrada se produzca en el punto crítico. Dependiendo de cómo se deshabiliten las señales, puede ser seguro llamar desde un manejador de señal, aunque en este ejemplo particular todavía existe la cuestión de que el parámetro pasado a la devolución de llamada sea el mismo para llamadas separadas. Sin embargo, aún puede salir mal con múltiples subprocesos.

En la práctica, no seguro para subprocesos a menudo implica no reentrada, ya que (informalmente) cualquier cosa que pueda salir mal debido a la interrupción del hilo por el programador, y la función llamada nuevamente desde otro hilo, también puede salir mal si el el hilo es interrumpido por una señal, y la función es llamada nuevamente desde el manejador de señal. Pero luego la "solución" para evitar las señales (deshabilitarlas) es diferente de la "solución" para evitar la concurrencia (bloqueos, por lo general). Esta es, en el mejor de los casos, una regla empírica.

Tenga en cuenta que he implícito globales aquí, pero exactamente las mismas consideraciones se aplicarían si la función tomara como parámetro un puntero al contador y al bloqueo. Es solo que los diversos casos serían inseguros o no reentrantes cuando se invocan con el mismo parámetro, en lugar de cuando se invocan.

¿Cuál es la diferencia entre los conceptos de "Reentrada de códigos" y "Seguridad de subprocesos" ? Según el enlace que se menciona a continuación, un fragmento de código puede ser cualquiera de ellos, ambos o ninguno de ellos.

Código de seguridad reentrante y subproceso

No pude entender la explicación claramente. La ayuda sería apreciada


El código de reentrada no tiene estado en un solo punto. Puede invocar el código mientras algo se está ejecutando en el código. Si el código utiliza un estado global, una llamada puede sobreescribir el estado global, rompiendo el cómputo en la otra llamada.

El código de seguridad del hilo es código sin condiciones de carrera u otros problemas de concurrencia. Una condición de carrera es cuando el orden en el que dos hilos hacen algo afecta el cálculo. Un problema de simultaneidad típico es cuando un cambio en una estructura de datos compartida puede completarse parcialmente y dejarse en un estado incoherente. Para evitar esto, debe usar mecanismos de control de simultaneidad como semáforos de mutexes para garantizar que nada más pueda acceder a la estructura de datos hasta que se complete la operación.

Por ejemplo, un fragmento de código puede ser no reentrante pero no susceptible a subprocesos si está protegido externamente por un mutex pero aún tiene una estructura de datos global donde el estado debe ser consistente durante toda la duración de la llamada. En este caso, el mismo hilo podría iniciar una devolución de llamada en el procedimiento mientras está protegido por un mutex de grano grueso externo. Si la devolución de llamada se produjo desde dentro del procedimiento de no reentrada, la llamada podría dejar la estructura de datos en un estado que podría romper el cálculo desde el punto de vista de la persona que llama.

Un fragmento de código puede ser reentrante pero no seguro para subprocesos si puede realizar un cambio no atómico a una estructura de datos compartida (y compartible) que podría interrumpirse en el medio de la actualización, dejando la estructura de datos en un estado incosistente. . En este caso, otro subproceso que acceda a la estructura de datos podría verse afectado por la estructura de datos medio modificada y bloquearse o realizar una operación que dañe los datos.