¿Debo ocuparme de las condiciones de la carrera que casi con seguridad no tienen posibilidades de ocurrir?

52

Consideremos algo como una aplicación GUI donde el subproceso principal está actualizando la interfaz de usuario casi instantáneamente, y algún otro subproceso está sondeando datos a través de la red o algo que se garantiza que demorará entre 5 y 10 segundos para finalizar el trabajo.

He recibido muchas respuestas diferentes para esto, pero algunas personas dicen que si se trata de una condición racial de una imposibilidad estadística, no se preocupe en absoluto, pero otros han dicho que si hay incluso un 10 -53 % (no bromeo con los números, esto es lo que he escuchado) de que algo de magia vudú ocurre debido a una condición de carrera, siempre obtenga / libere bloqueos en el hilo que lo necesita.

¿Cuáles son tus pensamientos? ¿Es una buena práctica de programación manejar la condición de carrera en situaciones estadísticamente imposibles? ¿O sería totalmente innecesario o incluso contraproducente agregar más líneas de código para dificultar la legibilidad?

    
pregunta l46kok 10.08.2015 - 00:38

16 respuestas

136

Si realmente es un evento 1 en 10 ^ 55, no habría necesidad de codificarlo. Eso implicaría que si hicieras la operación 1 millón de veces por segundo, obtendrías un error cada 3 * 10 ^ 41 años, que es, aproximadamente, 10 ^ 31 veces la edad del universo. Si su aplicación tiene un error solo una vez en cada billón de billones de billones de edades del universo, probablemente sea lo suficientemente confiable.

Sin embargo, apostaría fuertemente a que el error no es tan improbable. Si puede concebir el error, es casi seguro que ocurrirá al menos ocasionalmente, por lo que, para empezar, vale la pena codificarlo correctamente. Además, si codifica los subprocesos correctamente desde el principio para que obtengan y liberen los bloqueos adecuadamente, el código será mucho más fácil de mantener en el futuro. No tiene que preocuparse cuando está haciendo un cambio, tiene que volver a analizar todas las condiciones potenciales de la carrera, volver a calcular sus probabilidades y asegurarse de que no volverán a ocurrir.

    
respondido por el Justin Cave 17.08.2012 - 05:47
69

Desde el punto de vista de costo-beneficio, debe escribir un código adicional solo cuando obtenga suficiente beneficio.

Por ejemplo, si lo peor que pasaría si un hilo incorrecto "gana la carrera" es que la información no se mostraría y el usuario tendría que hacer clic en "actualizar", no se moleste en protegerse contra la condición de la carrera : tener que escribir una gran cantidad de código no vale la pena arreglar algo tan insignificante.

Por otra parte, si la condición de carrera podría resultar en transferencias de dinero incorrectas entre cuentas bancarias, entonces debe protegerse contra la condición de carrera sin importar cuánto código necesite escribir para resolver este problema.

    
respondido por el dasblinkenlight 17.08.2012 - 05:50
45

Encontrar una condición de carrera es la parte difícil. Probablemente pasaste casi todo el tiempo escribiendo esta pregunta, ya que te habría costado solucionarlo. No es como que lo hace mucho menos legible. Los programadores esperan ver el código de sincronización en tales situaciones, y en realidad podrían perder más tiempo preguntándose por qué no está allí y si agregarlo solucionaría su error no relacionado.

En cuanto a las probabilidades, te sorprenderías. El año pasado recibí un informe de error de condición de carrera que no pude reproducir con miles de intentos automáticos, pero el sistema uno de un lo vio todo el tiempo. El valor comercial de gastar 5 minutos para solucionarlo ahora, en lugar de solucionar el problema de un error "imposible" en la instalación de un cliente, hace que la elección no sea un problema.

    
respondido por el Karl Bielefeldt 17.08.2012 - 06:37
27

Obtener y liberar los bloqueos. Las probabilidades cambian, los algoritmos cambian. Es un mal hábito meterse, y cuando algo sale mal, no tienes que detenerte y preguntarte si tienes las probabilidades equivocadas ...

    
respondido por el jmoreno 17.08.2012 - 05:53
13
  

y algún otro subproceso está sondeando datos a través de la red o algo que se garantiza que demorará entre 5 y 10 segundos para finalizar el trabajo.

Hasta que alguien introduzca una capa de almacenamiento en caché para mejorar el rendimiento. De repente, la otra banda de rodadura terminó casi instantáneamente y la condición de la raza se manifiesta con mayor frecuencia.

Si esto hubiera sucedido exactamente hace unas semanas, tardaron aproximadamente 2 días completos para encontrar el error.

Siempre arregla las condiciones de la carrera si las reconoces.

    
respondido por el Michael Borgwardt 17.08.2012 - 15:12
8

Simple vs correcto.

En muchos casos, la simplicidad triunfa sobre la corrección. Es un problema de costo.

Además, las condiciones de carrera son cosas desagradables que tienden a no obedecer estadísticas simples. Todo va bien hasta que alguna otra sincronización aparentemente no relacionada hace que su condición de carrera suceda repentinamente la mitad del tiempo. A menos que active los registros o depure el código, por supuesto.

Una alternativa pragmática a la prevención de una condición de carrera (que puede ser complicada) puede ser detectarla y registrarla (bonificación por fallar en las primeras etapas). Si nunca sucede, perdiste poco. Si realmente sucede, tienes una justificación sólida para dedicar el tiempo extra a solucionarlo.

    
respondido por el ptyx 17.08.2012 - 06:46
7

Si su condición de carrera está relacionada con la seguridad, siempre debe codificar para evitarlo.

Un ejemplo común son las condiciones de carrera con la creación / apertura de archivos en Unix, que en algunas circunstancias pueden provocar ataques de escalamiento de privilegios si el programa con la condición de carrera se ejecuta con privilegios más altos que el usuario que interactúa con él, como un sistema. Proceso de daemon o peor aún, el kernel.

Incluso si una condición de carrera tiene una probabilidad de 10 ^ (- 80) de suceder al azar , puede darse el caso de que un atacante determinado tenga una probabilidad decente de crear tales condiciones de manera deliberada y artificial. .

    
respondido por el Bristol 17.08.2012 - 13:30
6

Therac-25!

Los desarrolladores del proyecto Therac-25 confiaban bastante en la sincronización entre una interfaz de usuario y un problema relacionado con la interfaz en una máquina terapéutica XRAY.

No deberían haber sido.

Puede obtener más información sobre este famoso desastre del software de vida o muerte en:

enlace

o

enlace

Su aplicación puede ser mucho menos sensible a fallas que los dispositivos médicos. Un método útil es calificar la exposición al riesgo como el producto de la probabilidad de ocurrencia y el costo de ocurrencia durante la vida útil del producto para todas las unidades que podrían producirse.

Si eligió compilar su código para que dure (y parece que lo ha hecho), debería considerar la ley de Moore, que puede eliminar fácilmente varios ceros cada pocos años a medida que las computadoras dentro o fuera de su sistema se vuelven más rápidas. Si envía miles de copias, corte más ceros. Si los usuarios realizan esta operación diariamente (o mensualmente) durante años, retire algunos más. Si se usa donde está disponible la fibra de Google, ¿entonces qué? Si la basura de la interfaz de usuario recolecta una operación GUI media, ¿eso afecta la carrera? ¿Está utilizando una biblioteca de código abierto o de Windows detrás de su GUI? ¿Las actualizaciones pueden afectar el tiempo?

Los semáforos, bloqueos, exclusión mutua, sincronización de barreras son algunas de las formas de sincronizar actividades entre subprocesos. Potencialmente, si no los está utilizando, otra persona que mantiene su programa puede hacerlo y luego las suposiciones sobre las relaciones entre los hilos pueden cambiar y el cálculo sobre la condición de la carrera podría ser invalidado.

Le recomiendo que realice una sincronización explícita porque, si bien es posible que nunca vea que se crea un problema, un cliente puede hacerlo. Además, incluso si su condición de raza nunca ocurre, qué sucede si usted o su organización son llamados a los tribunales para defender su código (ya que Toyota estaba relacionado con el Prius hace unos años). Cuanto más completa sea su metodología, mejor le irá. Podría ser mejor decir "nos protegemos contra este caso improbable como este ..." que decir "sabemos que nuestro código fallará, pero escribimos esta ecuación para demostrar que no sucederá en nuestra vida. Probablemente. "

Parece que el cálculo de probabilidad proviene de otra persona. ¿Conocen su código y los conocen lo suficiente como para confiar en que no se cometió ningún error? Si calculé un 99,999997% de confiabilidad para algo, también podría recordar mis clases de estadísticas universitarias y recordar que no siempre obtuve el 100%, y retrocedí un poco por ciento en mis estimaciones de confiabilidad personal.

    
respondido por el DeveloperDon 21.08.2012 - 05:17
4
  

¿sería totalmente innecesario o incluso contraproducente agregar más líneas de código para dificultar la legibilidad?

La simplicidad solo es buena cuando también es correcta. Dado que este código no es correcto, los futuros programadores inevitablemente lo verán cuando busquen un error relacionado.

De cualquier forma que lo maneje (ya sea al registrarlo, documentarlo o agregar los bloqueos, esto depende del costo), ahorrará tiempo a otros programadores cuando examine el código.

    
respondido por el Darthfett 17.08.2012 - 16:26
3

Esto dependería del contexto. Si es un juego casual de iPhone, probablemente no. El sistema de control de vuelo para el próximo vehículo espacial tripulado, probablemente. Todo depende de cuáles sean las consecuencias si el resultado "malo" ocurre comparado con el costo estimado de su reparación.

Rara vez hay una respuesta de 'talla única' para este tipo de preguntas porque no son preguntas de programación ni , sino preguntas económicas.

    
respondido por el GrandmasterB 17.08.2012 - 05:54
3

Sí, espera lo inesperado. He pasado horas (en el código de otras personas ^^) buscando condiciones que nunca deberían suceder.

Cosas como siempre tienen otra cosa, siempre tienen un valor predeterminado en el caso, inicializan variables (sí, realmente ... los errores ocurren a partir de esto), revisa tus bucles para las variables reutilizadas para cada iteración, etc.

Si le preocupan los problemas de subprocesos específicamente, lea blogs, artículos y libros sobre el tema. El tema actual parece ser datos inmutables.

    
respondido por el Paul 17.08.2012 - 17:09
3

Solo arréglalo.

He visto exactamente esto. Un subproceso logra realizar una solicitud de red a un servidor que realiza una búsqueda de base de datos compleja y responde antes de que el otro subproceso llegue a la siguiente línea de código. Sucede.

Algún cliente en algún lugar decidirá un día ejecutar algo que consuma todo el tiempo de CPU para el subproceso "rápido" mientras deja el subproceso lento en ejecución, y lo lamentará :)

    
respondido por el JohnB 17.08.2012 - 17:48
1

Si ha reconocido una condición de carrera improbable, ¡al menos documéntela en el código!

EDITAR: Debería agregar que lo arreglaría si fuera posible, pero al momento de escribir la respuesta anterior, ninguna otra respuesta dijo explícitamente que al menos documentara el problema en el código.

    
respondido por el Mark Hurd 22.08.2012 - 09:01
0

Pienso que si ya sabes cómo y por qué podría suceder, bien podría tratarlo. Es decir, si no ocupa una gran cantidad de recursos.

    
respondido por el Sjaak van der Heide 17.08.2012 - 15:07
0

Todo depende de cuáles sean las consecuencias de una condición de carrera. Creo que las personas que responden a su pregunta son correctas para su línea de trabajo. El mío son los motores de configuración del router. Para mí, las condiciones de la carrera hacen que los sistemas se detengan, se corrompan o se desconfiguren aunque haya dicho que fue exitoso. Siempre uso semáforos por enrutador para no tener que limpiar nada a mano.

Creo que parte de mi código GUI todavía es propenso a las condiciones de carrera de tal manera que a un usuario se le puede dar un error porque se produjo una condición de carrera, pero no tendría ninguna posibilidad si la probabilidad de corrupción de datos o mal comportamiento de la aplicación después de tal evento.

    
respondido por el Sylwester 18.08.2012 - 02:34
0

Curiosamente, encontré este problema recientemente. Ni siquiera me di cuenta de que una condición de carrera era posible en mi circunstancia. La condición de carrera solo se presentó cuando los procesadores de varios núcleos se convirtieron en la norma.

El escenario fue más o menos así. Un controlador de dispositivo levantó eventos para que el software los manejara. El control tuvo que volver al controlador del dispositivo lo antes posible para evitar un tiempo de espera en el dispositivo. Para garantizar esto, el evento se registró y se puso en cola en un hilo separado.

Receive event from device:
{
    Record event details.
    Enqueue event in the queuing thread.
    Acknowledge the event.
}

Queueing thread receives an event:
{
    Retrieve event details.
    Process event.
    Send next command to device.
}

Esto funcionó bien durante años. Entonces, de repente, fallaría en ciertas configuraciones. Resulta que el subproceso de cola ahora se estaba ejecutando verdaderamente en paralelo al subproceso de manejo de eventos, en lugar de compartir el tiempo de un solo procesador. Logró enviar el siguiente comando al dispositivo antes de que se reconociera el evento, lo que provocó un error de fuera de secuencia.

Dado que solo afectó a un cliente en una configuración, puse vergonzosamente un Thread.Sleep(1000) en donde estaba el problema. No ha habido un problema desde entonces.

    
respondido por el Hand-E-Food 18.08.2012 - 13:01

Lea otras preguntas en las etiquetas