Varios aspectos contribuyen a la definición de corrección en un programa concurrente:
* Seguridad: El programa nunca ingresa a un estado inválido. Esto incluye evitar problemas como:
* carreras de datos: Múltiples hilos que acceden y modifican la misma ubicación de memoria compartida sin una sincronización adecuada, lo que lleva a resultados impredecibles.
* Deadlocks: Dos o más hilos están bloqueados indefinidamente, esperando mutuamente para liberar recursos.
* LIVLOCKS: Los hilos están cambiando continuamente el estado en respuesta entre sí, pero ninguno progresa.
* hambre: Uno o más hilos se le niegan el acceso perpetuamente a un recurso compartido.
* Condiciones de carrera: El resultado depende del orden impredecible en el que se ejecutan los hilos.
* Livividad: El programa finalmente avanza y termina si se supone que debe hacerlo. Esto incluye garantizar que:
* Los hilos eventualmente adquieren los recursos necesarios.
* El programa finalmente llega a un estado de terminación.
* funcionalidad: El programa produce la salida correcta y logra su propósito previsto. Esto es similar a los programas secuenciales, pero complicado por la naturaleza concurrente de la ejecución. El resultado final debe ser consistente en todos los escenarios de ejecución posibles.
Por lo tanto, demostrar la corrección de un programa concurrente generalmente implica demostrar que:
1. Todas las entradas posibles de las ejecuciones de subprocesos conducen a un estado final válido. . Esto es increíblemente desafiante y a menudo poco práctico de hacer exhaustivamente.
2. El programa está libre de violaciones de seguridad (muertos muertos, carreras de datos, etc.). Esto a menudo se aborda a través de un diseño cuidadoso y el uso de mecanismos de sincronización (mutexes, semáforos, monitores, etc.).
3. El programa satisface sus propiedades de Lucial. Esto significa demostrar que el programa eventualmente completará sus tareas y no se atascará en un bucle o bloqueo muerto infinito.
En resumen, la corrección en la programación concurrente significa garantizar un comportamiento predecible y confiable en todos los horarios de ejecución posibles. Esto requiere una atención meticulosa a la sincronización, la gestión de recursos y las rigurosas técnicas de prueba y verificación. Los métodos formales se pueden emplear para una verificación rigurosa, pero a menudo son computacionalmente caros y solo aplicables a programas más pequeños. Por lo tanto, generalmente se requiere una combinación de diseño cuidadoso, pruebas y verificación potencialmente formal para garantizar la corrección de un programa concurrente.