Compartir a través de


Instrucciones de diseño de subprocesos

En las reglas siguientes se describen las instrucciones de diseño de implementación de subprocesos:

  • Evite proporcionar métodos estáticos que modifiquen el estado estático. En los escenarios de servidor habituales, el estado estático se comparte entre solicitudes, lo que significa que varios subprocesos pueden ejecutar ese código al mismo tiempo. Esto abre la posibilidad de errores en el subproceso. Considere la posibilidad de utilizar un modelo de diseño que encapsule los datos en instancias que no se compartan entre solicitudes.

  • El estado estático debe ser seguro para la ejecución de subprocesos.

  • No es necesario que el estado de la instancia sea seguro para la ejecución de subprocesos. De forma predeterminada, las bibliotecas de clases no deberían ser seguras para la ejecución de subprocesos. La agregación de bloqueos para crear un código seguro para la ejecución de subprocesos reduce el rendimiento y aumenta la contención de bloqueos, con lo que se crea la posibilidad de que se produzcan errores en el bloqueo. En los modelos habituales de aplicaciones, un solo subproceso ejecuta el código de usuario cada vez, lo que minimiza la necesidad de seguridad para subprocesos. Por este motivo, las bibliotecas de clases de .NET Framework no son de forma predeterminada seguras para la ejecución de subprocesos. En los casos en los que desee proporcionar una versión segura para ejecutar subprocesos, proporcione un método Synchronized estático que devuelva una instancia segura para la ejecución de subprocesos de un tipo. Para examinar un ejemplo, vea el método System.Collections.ArrayList.Synchronized y el método System.Collections.ArrayList.IsSynchronized.

  • Diseñe la biblioteca teniendo en cuenta la carga de ejecución en un escenario de servidor. Evite utilizar bloqueos siempre que sea posible.

  • Tenga en cuenta las llamadas a métodos en las secciones bloqueadas. Los bloqueos se pueden producir cuando el método estático de una clase A llama a los métodos estáticos de la clase B y viceversa. Si A y B sincronizan sus métodos estáticos, se producirá un bloqueo. Puede ocurrir que este bloqueo se descubra sólo en condiciones de una gran carga de subprocesos.

  • Se pueden producir problemas de rendimiento cuando un método estático en la clase A llame a un método estático en la clase A. Si estos métodos no están correctamente factorizados, esto afectará al rendimiento porque habrá una gran cantidad de sincronización redundante. El uso excesivo de una sincronización más flexible y detallada puede tener un impacto negativo en el rendimiento. Además, puede tener un impacto muy negativo en la escalabilidad.

  • Tenga en cuenta los problemas con la instrucción lock (SyncLock en Visual Basic). Resulta más apetecible utilizar la instrucción lock para solucionar todos los problemas de los subprocesos. Sin embargo, la Clase System.Threading.Interlocked es mejor para las actualizaciones que deban ser atómicas. Esta clase ejecuta un prefijo lock si no hay contención. En una revisión de código, tenga cuidado con instancias como la que se muestra en el ejemplo siguiente.

    SyncLock Me
       myField += 1
    End SyncLock
    [C#]
    lock(this) 
    {
       myField++;
    }
    

    Si se reemplaza el ejemplo anterior con el siguiente, se mejorará el rendimiento.

    System.Threading.Interlocked.Increment(myField)
    [C#]
    System.Threading.Interlocked.Increment(myField);
    

    Otro ejemplo es actualizar la variable de un tipo de objeto sólo si es null (Nothing en Visual Basic). Para actualizar la variable y hacer el código seguro para subprocesos, Se puede usar el código siguiente.

    If x Is Nothing Then
       SyncLock Me
          If x Is Nothing Then
             x = y
          End If
       End SyncLock
    End If
    [C#]
    if (x == null)
    {
       lock (this)
       {
          if (x == null)
          {
             x = y;
          }
       }
    }
    

    Se puede mejorar el rendimiento del ejemplo anterior cambiando el código por lo siguiente.

    System.Threading.Interlocked.CompareExchange(x, y, Nothing)
    [C#]
    System.Threading.Interlocked.CompareExchange(ref x, y, null);
    
  • Evite la necesidad de sincronización siempre que sea posible. En las rutas de mucho tráfico, es mejor evitar la sincronización. Algunas veces se puede ajustar el algoritmo para tolerar las condiciones de anticipación, en vez de eliminarlas.

Vea también

Instrucciones de diseño para programadores de bibliotecas de clases | Cambio en el lenguaje de Visual Basic | Espacio de nombres System.Threading