Descripción de las condiciones de anticipación e interbloqueos

Resumen

Visual Basic .NET o Visual Basic 2005 ofrece la posibilidad de utilizar subprocesos en aplicaciones de Visual Basic por primera vez. Subprocesos presentan problemas de depuración, como las condiciones de anticipación e interbloqueos. Este artículo explora estos dos problemas.

Más información

Condiciones de carrera

Se produce una condición de carrera cuando dos subprocesos tienen acceso a una variable compartida al mismo tiempo. El primer subproceso lee la variable, y el segundo subproceso lee el mismo valor de la variable. Los subprocesos de primer y segundo subproceso realizan sus operaciones en el valor, y de anticipación para ver qué subproceso puede escribir el valor del último a la variable compartida. Del subproceso que escribe su valor último se conserva el valor, porque el subproceso está escribiendo sobre el valor que escribió la conversación anterior.

Ejemplo y detalles

Cada subproceso se asigna un período predefinido de tiempo de ejecución en un procesador. Cuando caduca el tiempo asignado para el subproceso, se guarda el contexto del subproceso hasta su próximo turno en el procesador y el procesador comienza la ejecución del subproceso siguiente.

¿Cómo puede producir una condición de anticipación un comando de una línea? Examine el siguiente ejemplo para ver cómo se produce una condición de anticipación. Hay dos subprocesos y ambos están actualizando una variable compartida denominada total (que se representa como dword ptr ds: [031B49DCh] en el código de ensamblado).

Código de Visual Basic:
   'Thread 1   Total = Total + val1

   'Thread 2   Total = Total - val2

Código de ensamblado (con números de línea) de la compilación del código Visual Basic anterior:
 'Thread 1 1.   mov         eax,dword ptr ds:[031B49DCh] 
2. add eax,edi
3. jno 00000033
4. xor ecx,ecx
5. call 7611097F
6. mov dword ptr ds:[031B49DCh],eax

 'Thread 2 1.   mov         eax,dword ptr ds:[031B49DCh] 
2. sub eax,edi
3. jno 00000033
4. xor ecx,ecx
5. call 76110BE7
6. mov dword ptr ds:[031B49DCh],eax

Examinando el código del ensamblado, puede ver cuántas operaciones el procesador está realizando en el nivel inferior para ejecutar un cálculo de suma simple. Un subproceso puede ejecutar todo o parte de su código de ensamblado durante su tiempo en el procesador. Ahora observemos cómo se produce una condición de carrera de este código.

Total es 100, val1 es 50 y val2 es 15. El subproceso 1 Obtiene una oportunidad de ejecutarse pero sólo completa los pasos 1 a 3. Esto significa que el subproceso 1 leer la variable y completado la incorporación. El subproceso 1 es ahora esperando para escribir su nuevo valor de 150. Una vez que se detiene el subproceso 1, subproceso 2 obtiene ejecutar completamente. Esto significa que se ha escrito el valor que calcula (85) a la variable total. Finalmente, el subproceso 1 recupera el control y finaliza la ejecución. Escribe su valor (150). Por lo tanto, cuando haya finalizado el subproceso 1, el valor del Total ahora es 150 en lugar de 85.


Puede ver cómo esto podría ser un problema importante. Si se tratara de un programa en un banco, el cliente tendría dinero de su cuenta que no debería estar presente.


Este error es aleatorio, ya que es posible para el subproceso 1 completar su ejecución antes de su tiempo en caduca el procesador y, a continuación, subproceso 2 puede comenzar su ejecución. Si se producen estos eventos, el problema no se produce. La ejecución del subproceso no es determinista, por lo tanto, no puede controlar el tiempo o el orden de ejecución. Tenga en cuenta que los subprocesos pueden ejecutarse de forma diferente en tiempo de ejecución en comparación con el modo de depuración. Asimismo, puede ver que si cada subproceso se ejecuta en serie, el error no se produce. Esta aleatoriedad hace que sea mucho más difíciles de localizar y depurar estos errores.


Para evitar condiciones de carrera, puede bloquear las variables compartidas, por lo que sólo un subproceso cada vez tenga acceso a la variable compartida. Hacerlo con moderación, porque si una variable está bloqueada en el subproceso 1 y subproceso 2 también necesita la variable, se detiene la ejecución del subproceso 2 mientras espera subproceso 2 subproceso 1 liberar la variable. (Para obtener más información, consulte "SyncLock" en la sección "Referencias" de este artículo).

Síntomas

El síntoma más común de una condición de carrera es impredecibles valores de las variables que se comparten entre varios subprocesos. Esto es consecuencia de la imprevisión de la orden en el que se ejecutan los subprocesos. En algún momento un subproceso wins y en algún momento el otro wins subproceso. En otras ocasiones, ejecución funciona correctamente. Además, si cada subproceso se ejecuta por separado, el valor de la variable se comporta correctamente.


Interbloqueos

Un interbloqueo se produce cuando dos subprocesos cada uno bloquear una variable diferente al mismo tiempo y vuelva a bloquear la variable que el otro subproceso ya bloqueado. Como resultado, cada subproceso deja de ejecutarse y espera a que el otro subproceso libera la variable. Dado que cada subproceso mantiene la variable que desea que el otro subproceso, no ocurre nada, y los subprocesos permanecen bloqueados.

Ejemplo y detalles

El código siguiente tiene dos objetos, LeftVal y RightVal:

'Thread 1SyncLock LeftVal
SyncLock RightVal
'Perform operations on LeftVal and RightVal that require read and write.
End SyncLock
End SyncLock

'Thread 2SyncLock RightVal
SyncLock LeftVal
'Perform operations on RightVal and LeftVal that require read and write.
End SyncLock
End SyncLock

Un interbloqueo se produce cuando el subproceso 1 puede bloquear LeftVal. El procesador detiene la ejecución del subproceso 1 y comienza la ejecución del subproceso 2. El subproceso 2 bloqueos RightVal y, a continuación, intenta bloquear LeftVal. Porque está bloqueada LeftVal, subproceso 2 se detiene y espera LeftVal liberarse. Porque se ha detenido el subproceso 2, subproceso 1 se permite que continúe ejecutándose. El subproceso 1 intenta bloquear RightVal pero no, porque el subproceso 2 ha bloqueado. Como resultado, subproceso 1 comienza a esperar hasta que RightVal esté disponible. Cada subproceso espera el otro subproceso, porque cada subproceso ha bloqueado la variable que el otro subproceso está esperando, y ninguno de los subprocesos es desbloquear la variable que lo contiene.


Un interbloqueo no siempre es así. Si el subproceso 1 ejecuta ambos bloqueos antes de que el procesador detiene, subproceso 1 puede realizar sus operaciones y, a continuación, desbloquear la variable compartida. Después de que la variable desbloquea el subproceso 1, subproceso 2 puede continuar con su ejecución, como se esperaba.


Este error parece obvio cuando estos fragmentos de código se colocan uno junto al otro, pero en la práctica, puede aparecer el código en módulos separados o áreas del código. Este un error muy difícil de localizar porque, desde este mismo código, pueden producirse la ejecución correcta y ejecución incorrecta.

Síntomas

Un síntoma común de interbloqueo es que el programa o el grupo de subprocesos deja de responder. Esto también es conocido como un bloqueo. Al menos dos subprocesos están esperando en cada variable que el otro subproceso bloqueado. Los subprocesos no continúe, porque ninguno de los subprocesos publicará su variable hasta que llegue la otra variable. Todo el programa puede bloquearse si el programa está esperando en uno o ambos de estos subprocesos para la ejecución completa.

¿Qué es un subproceso?

Los procesos se utilizan para separar las diferentes aplicaciones que se ejecutan en un momento determinado en un solo equipo. El sistema operativo no ejecuta los procesos, pero sí de subprocesos. Un subproceso es una unidad de ejecución. El sistema operativo asigna tiempo de procesador para un subproceso para la ejecución de tareas del subproceso. Un solo proceso puede contener varios subprocesos de ejecución. Cada subproceso mantiene sus propios controladores de excepciones, programación de prioridades y un conjunto de estructuras que el sistema operativo utiliza para guardar el contexto del subproceso si el subproceso no puede completar su ejecución durante el tiempo que se asignó al procesador. El contexto se mantiene hasta la próxima vez que el subproceso recibe tiempo de procesador. El contexto incluye toda la información que el subproceso necesita para continuar su ejecución de forma transparente. Esta información incluye el conjunto de registros del procesador y la pila de llamadas en el espacio de direcciones del proceso del host.

Referencias

Para obtener más información, busque las siguientes palabras clave en la Ayuda de Visual Studio:
  • SyncLock. Permite que un objeto debe estar bloqueado. Si otro subproceso intenta bloquear ese mismo objeto, se bloquea hasta que el primer subproceso libera. Utilizar SyncLock con cuidado, porque el mal uso de SyncLock pueden ocasionar problemas. Por ejemplo, este comando puede evitar condiciones de carrera, pero producir interbloqueos.
  • Entrelazadas. Permite que un conjunto de operaciones seguras para subprocesos en variables numéricas básicas.
Para obtener información adicional, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:

316422 INFO: Guía básica para el subprocesamiento en Visual Basic .NET
Para obtener más información, consulte el siguiente sitio Web de MSDN:
Propiedades

Id. de artículo: 317723 - Última revisión: 17 ene. 2017 - Revisión: 1

Comentarios