tpl programming parallel paralelismo new net examples c# .net vb.net parallel-processing

programming - tpl c#



Pruebas unitarias, interbloqueos y condiciones de carrera (7)

No creo que buscar las condiciones de carrera realmente caiga en el reino de las pruebas unitarias. Más o menos por definición, la única manera de probar las condiciones de carrera es pseudoaleatoriamente. A menos que esté dispuesto a hacer el esfuerzo de probar formalmente la corrección de su estrategia de bloqueo, tendrá que hacer algunas pruebas de estrés.

Aún necesita escribir pruebas unitarias, para verificar la corrección de los algoritmos, en lugar de la estrategia de bloqueo.

Cuando someta a prueba el código de subprocesos múltiples, querrá probar en condiciones en las que tenga una CPU por subproceso, donde tenga múltiples subprocesos que compartan la CPU y donde tenga más CPU que subprocesos (si es posible).

¿Alguna sugerencia sobre cómo escribir pruebas de unidad repetibles para el código que puede ser susceptible a interbloqueos y condiciones de carrera?

En este momento me inclino por omitir las pruebas unitarias y centrarme en las pruebas de estrés. El problema con eso es que puedes realizar una prueba de esfuerzo 5 veces y ver cinco resultados diferentes.

EDITAR: Sé que probablemente sea solo un sueño, pero si hubiera una manera de controlar los hilos individuales y hacer que ejecuten una instrucción a la vez, entonces podría llegar a algún lado.


No puedo pensar en una buena forma automatizada, pero lo más cerca que he llegado fue a escribir una prueba unitaria que ''expondría'' un punto muerto fue mediante el uso de puntos de corte además de una prueba unitaria. Simplemente agregué algunas instrucciones sobre dónde agregar el punto de interrupción. Hay un poco de esfuerzo manual involucrado, pero con ellos siempre puedes exponer tu peor calendario de subprocesos.

Tal vez alguien haya pensado una buena manera de automatizar este tipo de funcionalidad. Me podría imaginar ejecutar automáticamente el depurador, romper un hilo en una línea específica, dejar que otro se ejecute hasta una condición específica, y luego afirmar para la prueba unitaria.


Por lo general, es posible forzar las condiciones de carrera previstas y los bloqueos utilizando elementos como ManualResetEvent para poner cada hilo en el estado esperado antes de soltarlo, es decir, obtener el hilo A para tener el bloqueo y esperar una señal ... obtener el hilo B para solicitarlo el candado, etc ...

Sin embargo, normalmente puede escribir una prueba de este tipo para investigar un posible error, para comprobar cuándo se solucionó y si no vuelve a aparecer. Por lo general, diseñaría en función de las condiciones de carrera (pero pruébelas de la mejor manera posible).


Puede escribir una clase de bloqueo que detecte interbloqueos potenciales, observando el orden de las operaciones de bloqueo. Hacemos esto teniendo un contexto de hilo con el que todos los bloqueos se registran cuando se adquieren (se puede hacer una opción de solo DEPURAR).

La idea es crear un gráfico donde los nodos representen bloqueos y un borde dirigido entre A y B significa que "el bloqueo A estaba siendo retenido cuando se adquirió el bloqueo B". Deje que su programa se ejecute con cargas normales, luego verifique los ciclos en el gráfico. Un ciclo significa que existe la posibilidad de un punto muerto, incluso si su código no lo golpeó.


Anteriormente utilicé retrasos artificiales en el código que son activados por algunos parámetros en la solicitud. Por ejemplo, una solicitud le dice al servidor que demore la escritura entre dos escrituras y otra para hacerlas sin demora en el medio.

A Mark Bessey escribe, esto solo es útil para crear reprocesiones, no para descubrir el problema.