Componentes seguros para subprocesos
Compartir recursos entre subprocesos constituye una necesidad frecuente en la programación multiproceso.Por ejemplo, es posible que varios subprocesos necesiten obtener acceso a una base de datos compartida, o actualizar un conjunto de variables del sistema.Cuando más de un subproceso compite simultáneamente por obtener acceso a recursos compartidos existe la posibilidad de que se produzca una condición de carrera.Existe una condición de carrera cuando un subproceso modifica un recurso y lo deja en un estado no válido y, a continuación, otro subproceso intenta obtener acceso a ese recurso y usarlo en dicho estado no válido.Considere el ejemplo siguiente:
Public Class WidgetManipulator
Public TotalWidgets as Integer = 0
Public Sub AddWidget()
TotalWidgets += 1
Console.WriteLine("Total widgets = " & TotalWidgets.ToString)
End Sub
Public Sub RemoveWidgets()
TotalWidgets -= 10
End Sub
End Class
public class WidgetManipulator
{
public int TotalWidgets = 0;
public void AddWidget()
{
TotalWidgets++;
Console.WriteLine("Total widgets = " + TotalWidgets.ToString());
}
public void RemoveWidgets()
{
TotalWidgets -= 10;
}
}
Esta clase expone dos métodos.Un método, AddWidget, suma 1 al campo TotalWidgets y escribe el valor en la consola.El segundo método resta 10 del valor de TotalWidgets.Considere lo que ocurriría si dos subprocesos intentaran obtener acceso simultáneamente a la misma instancia de la clase WidgetManipulator.Un subproceso podría llamar a AddWidget al mismo tiempo que el segundo subproceso llama a RemoveWidgets.En ese caso, el valor de TotalWidgets podría ser modificado por el segundo subproceso antes de que el primer subproceso pudiera comunicar un valor exacto.Esta condición de carrera puede hacer que se comuniquen resultados inexactos y puede causar daños en los datos.
Evitar condiciones de carrera mediante bloqueos
Se pueden proteger las secciones vitales del código de las condiciones de carrera mediante el uso de bloqueos.Un bloqueo, representado en Visual Basic por la palabra clave SyncLock (Instrucción), o en C# por lock (Instrucción), permite que un único subproceso obtenga derechos de ejecución únicos sobre un objeto.En el ejemplo siguiente se ilustran los bloqueos:
SyncLock MyObject
' Insert code that affects MyObject.
End SyncLock
lock(MyObject)
{
// Insert code that affects MyObject.
}
Cuando se encuentra un bloqueo, la ejecución en el objeto especificado (MyObject en el ejemplo anterior) se bloquea hasta que el subproceso pueda obtener acceso único al objeto.Cuando se alcanza el fin del bloqueo, éste se libera y la ejecución procede de forma normal.Sólo se puede obtener un bloqueo sobre un objeto que devuelva una referencia.Un tipo de valor no se puede bloquear de este modo.
Desventajas de los bloqueos
Aunque los bloqueos garantizan que varios subprocesos no obtengan acceso simultáneamente a un objeto, pueden causar una degradación importante del rendimiento.Imagínese un programa con muchos subprocesos distintos ejecutándose.Si cada subproceso necesita usar un objeto determinado y tiene que esperar para obtener un bloqueo único sobre dicho objeto antes de ejecutarse, todos los subprocesos dejarán de ejecutarse y harán cola uno detrás de otro, produciendo un rendimiento muy bajo.Por estas razones, sólo se deberían usar bloqueos cuando haya código que debe ejecutarse como una unidad.Por ejemplo, podría actualizar varios recursos que sean interdependientes.Este código se conoce como atómico.Si los bloqueos se restringen sólo al código que se deba ejecutar de forma atómica, se podrán escribir componentes multiproceso que garanticen la seguridad de los datos a la par que un buen rendimiento.
Asimismo, debe tener cuidado para evitar situaciones en las que puedan producirse interbloqueos.Este caso se produce cuando existen al menos dos subprocesos que están esperando a que el otro libere ciertos recursos compartidos.Por ejemplo, el subproceso 1 puede bloquear el recurso A y estar esperando al recurso B.El subproceso 2, por otro lado, puede bloquear el recurso B y estar esperando al recurso A.En este caso, ninguno de los dos subprocesos podrá continuar.La única forma de evitar situaciones de interbloqueo es mediante una programación cuidadosa.
Vea también
Tareas
Cómo: Coordinar varios subprocesos de ejecución
Cómo: Manipular controles a partir de subprocesos
Tutorial: Crear un componente sencillo con múltiples procesos en Visual Basic
Tutorial: Crear un componente sencillo con múltiples procesos en Visual C#
Referencia
Conceptos
Información general sobre el modelo asincrónico basado en eventos