Cosa rende un metodo thread-safe? Quali sono le regole?

Cosa rende un metodo thread-safe? Quali sono le regole?

Se un metodo (istanza o statico) fa riferimento solo a variabili con ambito all'interno di quel metodo, allora è thread-safe perché ogni thread ha il proprio stack:

In questo caso, più thread potrebbero chiamare ThreadSafeMethod contemporaneamente senza problemi.

public class Thing
{
    public int ThreadSafeMethod(string parameter1)
    {
        int number; // each thread will have its own variable for number.
        number = parameter1.Length;
        return number;
    }
}

Questo vale anche se il metodo chiama altri metodi di classe che fanno riferimento solo a variabili con ambito locale:

public class Thing
{
    public int ThreadSafeMethod(string parameter1)
    {
        int number;
        number = this.GetLength(parameter1);
        return number;
    }

    private int GetLength(string value)
    {
        int length = value.Length;
        return length;
    }
}

Se un metodo accede a qualsiasi proprietà o campo (istanza o statico) (stato dell'oggetto), è necessario utilizzare i blocchi per garantire che i valori non vengano modificati da un thread diverso.

public class Thing
{
    private string someValue; // all threads will read and write to this same field value

    public int NonThreadSafeMethod(string parameter1)
    {
        this.someValue = parameter1;

        int number;

        // Since access to someValue is not synchronised by the class, a separate thread
        // could have changed its value between this thread setting its value at the start 
        // of the method and this line reading its value.
        number = this.someValue.Length;
        return number;
    }
}

Dovresti essere consapevole del fatto che tutti i parametri passati al metodo che non sono uno struct o immutabile potrebbero essere mutati da un altro thread al di fuori dell'ambito del metodo.

Per garantire una corretta concorrenza è necessario utilizzare il blocco.

per ulteriori informazioni, vedere riferimento C# all'istruzione di blocco e ReadWriterLockSlim.

blocca è utile principalmente per fornire una funzionalità alla volta,
ReadWriterLockSlim è utile se hai bisogno di più lettori e singoli scrittori.


Assolutamente no. Puoi scrivere un programma con una sola variabile locale a cui si accede da un singolo thread che tuttavia non è threadsafe:

https://stackoverflow.com/a/8883117/88656

Assolutamente no.

Assolutamente no. La caratteristica distintiva di una variabile locale è che è visibile solo all'interno dell'ambito locale , non che sia allocato nel pool temporaneo . È perfettamente legale ed è possibile accedere alla stessa variabile locale da due thread diversi. Puoi farlo utilizzando metodi anonimi, lambda, blocchi iteratori o metodi asincroni.

Assolutamente no.

Forse.

Dovrai imparare a convivere con la delusione. Questo è un argomento molto difficile.

No. Come hai visto dal mio esempio precedente un metodo vuoto può non essere thread-safe . Potresti anche chiedere "c'è un breve elenco di regole che garantisce che un metodo sia corretto ". No, non c'è. La sicurezza dei thread non è altro che un tipo di correttezza estremamente complicato.

Inoltre, il fatto che tu stia ponendo la domanda indica il tuo fondamentale malinteso sulla sicurezza dei thread. La sicurezza dei thread è globale , non un locale proprietà di un programma. Il motivo per cui è così difficile correggere è perché devi avere una conoscenza completa del comportamento di threading dell'intero programma al fine di garantirne la sicurezza.

Ancora una volta, guarda il mio esempio:ogni metodo è banale . È il modo in cui i metodi interagiscono tra loro a livello "globale" che rende il programma deadlock. Non puoi considerare ogni metodo e spuntarlo come "sicuro" e poi aspettarti che l'intero programma sia sicuro, non più di quanto tu possa concludere che poiché la tua casa è fatta al 100% di mattoni non cavi, anche la casa è non vuoto. Il vuoto di una casa è una proprietà globale dell'intera cosa, non un aggregato delle proprietà delle sue parti.


Non esiste una regola ferrea.

Ecco alcune regole per rendere sicuro il thread di codice in .NET e perché queste non sono buone regole:

  1. La funzione e tutte le funzioni che chiama devono essere pure (senza effetti collaterali) e utilizzare variabili locali. Anche se questo renderà il tuo codice thread-safe, ci sono anche pochissime cose interessanti che puoi fare con questa restrizione in .NET.
  2. Ogni funzione che opera su un oggetto comune deve lock su una cosa comune. Tutti i blocchi devono essere eseguiti nello stesso ordine. Ciò renderà il thread di codice sicuro, ma sarà incredibilmente lento e potresti anche non utilizzare più thread.
  3. ...

Non esiste una regola che renda sicuro il thread del codice, l'unica cosa che puoi fare è assicurarti che il tuo codice funzioni, non importa quante volte viene eseguito attivamente, ogni thread può essere interrotto in qualsiasi momento, con ogni thread in il proprio stato/posizione, e questo per ogni funzione (statica o meno) che accede a oggetti comuni.