Istruzioni di progettazione dei thread

Le istruzioni di progettazione per l'implementazione dei thread sono definite dalle regole riportate di seguito.

  • Evitare di fornire metodi static che modificano lo stato static. Negli scenari server comuni, lo stato static viene condiviso tra le richieste e, pertanto, più thread possono eseguire contemporaneamente tale codice. In questo modo è possibile che si verifichino errori dei thread. Provare a utilizzare un modello di progettazione che incapsula i dati nelle istanze che non sono condivise tra le richieste.

  • È necessario che lo stato static sia thread-safe.

  • Non è necessario che lo stato dell'istanza sia thread-safe. Per impostazione predefinita, è preferibile che le librerie di classi non siano thread-safe. Se si aggiungono blocchi per creare codice thread-safe, le prestazioni vengono ridotte, aumentano i conflitti di blocco ed è possibile che si verifichino errori di blocchi critici. Nei modelli applicativi comuni, solo un thread per volta esegue il codice utente riducendo la necessità di indipendenza dai thread. Per questo motivo, le librerie di classi di .NET Framework non sono thread-safe per impostazione predefinita. Nei casi in cui si desideri fornire una versione thread-safe, fornire un metodo Synchronized static per restituire un'istanza thread-safe di un tipo. Per un esempio, vedere Metodo System.Collections.ArrayList.Synchronized e Metodo System.Collections.ArrayList.IsSynchronized.

  • Progettare la libreria tenendo in mente il carico di esecuzione in uno scenario server. Evitare i blocchi quando è possibile.

  • Tenere in considerazione le chiamate ai metodi nelle sezioni bloccate. I blocchi critici possono verificarsi quando un metodo static nella classe A chiama i metodi static nella classe B e viceversa. Se A e B sincronizzano i relativi metodi static, verrà generato un blocco critico. È possibile che tale blocco critico venga individuato solo con un forte sovraccarico di thread.

  • I problemi relativi alle prestazioni possono verificarsi quando un metodo static nella classe A chiama un metodo static nella classe A. Se tali metodi non vengono scomposti correttamente, le prestazioni risulteranno ridotte poiché verrà eseguito un elevato numero di operazioni di sincronizzazione ridondanti. È possibile che un uso eccessivo della sincronizzazione specifica riduca notevolmente le prestazioni e abbia un effetto negativo sulla scalabilità.

  • Tenere presente le questioni relative all'istruzione lock (SyncLock in Visual Basic). L'istruzione lock viene utilizzata per tentare di risolvere tutti i problemi dei thread. La classe System.Threading.Interlocked rappresenta tuttavia una soluzione migliore per gli aggiornamenti, che devono essere atomici. Esegue un unico prefisso lock se non esistono conflitti. Nell'analisi del codice controllare le istanze simili a quella indicata nell'esempio riportato di seguito.

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

    Le prestazioni verranno migliorate sostituendo l'esempio precedente con quello riportato di seguito.

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

    Un altro esempio consiste nell'aggiornare una variabile del tipo oggetto solo se è null (Nothing in Visual Basic). È possibile utilizzare il codice riportato di seguito per aggiornare la variabile e rendere il codice thread-safe.

    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;
          }
       }
    }
    

    È possibile migliorare le prestazioni dell'esempio precedente sostituendolo con il codice riportato di seguito.

    System.Threading.Interlocked.CompareExchange(x, y, Nothing)
    [C#]
    System.Threading.Interlocked.CompareExchange(ref x, y, null);
    
  • Se possibile, evitare che sia necessario eseguire la sincronizzazione. Per i percorsi con traffico elevato è preferibile evitare la sincronizzazione. È possibile a volte modificare l'algoritmo in modo che le condizioni di conflitto siano tollerate anziché eliminate.

Vedere anche

Istruzioni di progettazione per gli sviluppatori di librerie di classi | Modifiche al linguaggio Visual Basic | Spazio dei nomi System.Threading