C #: cosa succede se un metodo statico viene chiamato da più thread?


93

Nella mia applicazione ho un metodo statico che viene chiamato da più thread contemporaneamente. C'è il pericolo che i miei dati vengano confusi?

Nel mio primo tentativo il metodo non era statico e stavo creando più istanze della classe. In quel caso i miei dati si sono confusi in qualche modo. Non sono sicuro di come ciò avvenga perché accade solo a volte. Sto ancora eseguendo il debug. Ma ora il metodo è statico, finora non ho problemi. Forse è solo fortuna. Non lo so per certo.


Risposte:


96

Le variabili dichiarate all'interno dei metodi (con la possibile eccezione delle variabili " catturate ") sono isolate, quindi non avrai problemi intrinseci; tuttavia, se il tuo metodo statico accede a uno stato condiviso, tutte le scommesse sono disattivate.

Esempi di stato condiviso potrebbero essere:

  • campi statici
  • oggetti a cui si accede da una cache comune (non serializzata)
  • dati ottenuti tramite i parametri di input (e lo stato su quegli oggetti), se è possibile che più thread stiano toccando lo stesso oggetto / i

Se hai uno stato condiviso, devi:

  • fai attenzione a non mutare lo stato una volta che può essere condiviso (meglio: usa oggetti immutabili per rappresentare lo stato e scatta un'istantanea dello stato in una variabile locale - cioè invece di fare riferimento whatever.SomeDataripetutamente, leggi whatever.SomeData una volta in una variabile locale, e poi usa semplicemente la variabile - nota che questo aiuta solo per lo stato immutabile!)
  • sincronizzare l'accesso ai dati (tutti i thread devono essere sincronizzati) - lettore / scrittore che si escludono a vicenda o (più granulare)

1
@Diego - quel commento è destinato a me o a @Holli?
Marc Gravell

A Holli, giusto per aggiungere alcune informazioni pratiche alla tua risposta.
Diego Pereyra

1
@ Marc Non posso essere completamente d'accordo con "Le variabili dichiarate all'interno dei metodi (con la possibile eccezione delle variabili" catturate ") sono isolate". Considera un file handle dichiarato in un metodo statico. Quindi un thread può accedere all'handle quando un altro thread lo utilizza. Porterà a comportamenti inaspettati. Oppure la tua variabile "catturata" significa anche "file handle".
prabhakaran

9
@prabhakaran se un file handle è una variabile di metodo, è limitato solo a quel chiamante. Qualsiasi altro chiamante parlerà con una variabile diversa (le variabili del metodo sono per chiamata). L'accesso al file sottostante è ora un problema separato, ma non è correlato a c # o .NET. Se l'handle non è condiviso, ci si aspetterebbe una sorta di mutex / lock se questo scenario è probabile.
Marc Gravell

28

Sì, è solo fortuna. ;)

Non importa se il metodo è statico o meno, ciò che conta è se i dati sono statici o meno.

Se ogni thread ha la propria istanza separata della classe con il proprio set di dati, non c'è rischio che i dati vengano confusi. Se i dati sono statici, esiste un solo set di dati e tutti i thread condividono gli stessi dati, quindi non c'è modo di non confonderli.

Quando i dati in istanze separate continuano a essere confusi, è molto probabile che i dati non siano realmente separati.


6
Mi è piaciuta quella linea - It doesn't matter if the method is static or not, what matters is if the data is static or not. Solo per aggiungere, le variabili locali dichiarate nell'ambito di un metodo statico non formano quella parte di dati di cui dobbiamo essere disturbati nello scenario dato.
RBT

Bella risposta. Mi ha aiutato molto.
Fractal

15

I metodi statici dovrebbero andare bene per più thread.

I dati statici d'altra parte potrebbero causare un problema perché i tentativi di accedere agli stessi dati da thread diversi devono essere controllati per garantire che solo un thread alla volta stia leggendo o scrivendo i dati.


2
La parola chiave qui è sincronizzazione :-)
G. Stoynev

2
la lettura è OK che avvenga contemporaneamente, ma la lettura E la scrittura contemporaneamente porteranno a un comportamento inaspettato
Freestyle076

9

MSDN dice sempre:

Tutti i membri statici pubblici (condivisi in Visual Basic) di questo tipo sono thread-safe. Non è garantito che tutti i membri dell'istanza siano thread-safe.

Modifica: come dicono i ragazzi qui, non è sempre il caso, e chiaramente questo si applica alle classi progettate in questo modo nel BCL, non alle classi create dall'utente in cui ciò non si applica.


3
Phew! Infine, ho capito il significato di questa nota che si trova così frequentemente nella documentazione MSDN. Quindi, fondamentalmente, quando MS progetta un metodo statico (dove è pubblicata questa nota) in BCL non accede a nessuna variabile / membro / stato che è al di fuori dell'ambito di quel metodo. Si basano completamente su variabili locali con scope metodo solo per implementare la logica di quel metodo. Molto contento che tu abbia condiviso.
RBT

@ Marcote, non è vero il contrario? I membri dell'istanza sono sicuri perché ce n'è uno per istanza. Tuttavia, i membri statici non sono thread-safe perché sono condivisi tra tutte le istanze di quella classe? quora.com/…
Fractal

1
dipende. Non tratterei mai un membro dell'istanza al sicuro per impostazione predefinita. Ecco perché un intero set di librerie e per evitare il danneggiamento dei dati tra molte altre cose.
Marcote

1
ok, grazie @ Marcote. Sto lentamente scoprendo che ho molto da imparare.
Fractal
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.