2009-08-08 12 views
18

Così abbiamo visto tutti la notifica Threading su MSDN per molti oggetti disponibili generici:Ciò che rende i membri dell'istanza thread-safe vs public static?

"statici pubblici (Shared in Visual Basic) di questo tipo sono thread-safe I membri di istanza non sono garantiti per essere sicuri thread. ".

La mia domanda è: cosa significa essere una variabile di istanza o una statica pubblica non è sicura?

+3

La parte tra parentesi è ciò che causa confusione durante la lettura, ma piuttosto come: statico pubblico * membri * di questo tipo sono thread-safe. Ciò significa che i membri statici di questo tipo di oggetto sono protetti da thread, non si riferiscono a un "tipo statico pubblico"; istanza dichiarata nel tuo codice. –

risposta

13

questo è vero solo in generale.

In generale metodi statici sono statici perché non dipendono né si accedere ai dati di istanza definito che un altro filo potrebbe anche accesso. In generale, le uniche variabili che (un metodo statico) utilizza sono variabili dichiarate e legato alla memoria statica della classe del metodo è implementato in, non alla memoria allocata per oggetto - (l'istanza della classe) creato per quell'oggetto . Un metodo statico non può e non può fare riferimento o utilizzare alcuna di tali variabili. Se un metodo utilizza questo tipo di variabile dati di istanza, legata a un'istanza specifica, non può essere statica. Un metodo di istanza, al contrario, accede ad alcuni elementi di dati (proprietà o campi) dell'istanza.

Se, OTOH, un metodo statico accede a una proprietà statica o campo della classe, è altrettanto non-thread safe.

Ci sono quattro condizioni necessarie affinché una gara sia possibile.

  1. La prima condizione è che ci sono posizioni di memoria che sono accessibili da più di un thread. In genere, queste posizioni sono variabili globali/statiche o la memoria heap è raggiungibile da variabili globali/statiche.
  2. La seconda condizione è che esiste una proprietà (spesso chiamata invariante), associata a queste posizioni di memoria condivisa che devono essere vere o valide affinché il programma funzioni correttamente. In genere, la proprietà deve rimanere true prima che si verifichi un aggiornamento affinché l'aggiornamento sia corretto.
  3. La terza condizione è che la proprietà invariabile non viene mantenuta durante una parte dell'aggiornamento effettivo. (È transitoriamente non valido o falso durante una parte dell'elaborazione).
  4. La quarta e ultima condizione che deve verificarsi perché una gara si verifichi è che un altro thread accede alla memoria mentre l'invariante è interrotto, causando in tal modo un comportamento incoerente o scorretto.
8

E 'il problema di stato. Ciò che rende generale i metodi non sicuri per più thread è che non accedono allo stato condiviso in modo thread-safe. I metodi statici in genere non accedono allo stato condiviso e quindi hanno meno probabilità di imbattersi in questo problema. È ancora possibile avere condizioni di gara in metodi statici/condivisi se toccano dati statici, ma i metodi statici in generale non lo sono in genere con i metodi statici.

+0

Forse dovresti sottolineare il fatto che è solo "in generale" di più. – Dykam

+0

@Dykam, sì ho messo in evidenza quella parte per l'enfasi – JaredPar

12

Nulla integrato rende statico più o meno differente (ri thread-sicurezza) di esempio, eccetto:

  • metodi statici sono metodi spesso senza stato "puri funzionali", rendendoli automaticamente thread-safe
  • v'è una chiara aspettativa sui membri statici per essere thread-safe (dal momento che non si può controllare ciò che veramente ogni thread sta facendo in una sola volta) - per cui è previsto che qualsiasi metodo statico che potrebbe rischio thread safety essere fatto thread-safe

Questo non è vero per i metodi di istanza:

  • metodi istanza comunemente accedono stato in tale istanza
  • v'è alcuna aspettativa di filo di sicurezza a meno che non sia esplicitato nella documentazione

Quindi, in generale, è previsto che il chiamante gestisce la sicurezza del thread su istanze.

Esistono eccezioni in cui le istanze sono thread-safe (in genere per cose strettamente legate al threading, come una coda producer-consumer) - ma IMO qualsiasi membro statico che non sia thread-safe è un bug.

+1

@marc, sono umilmente in disaccordo ... per non dire che tale non esiste, ma non ho mai avuto l'aspettativa che i metodi statici siano sicuri per i thread, né ho sentito parlare di tale aspettativa. I metodi statici possono ancora accedere a variabili statiche, (da qualsiasi classe), nonché variabili di istanza in oggetti passati come parametri del metodo. –

+0

(segue) L'unico modo per cui le vostre aspettative potrebbero essere invocate è se a tutti i metodi statici fosse proibito l'uso di variabili passate in riferimento o istanze di tipi di riferimento e dall'accesso a qualsiasi variabile statica in quella o in un'altra classe. Questa sembra essere una restrizione straordinariamente onerosa, solo per permettere alla tua "aspettativa" di essere affidabile. –

+0

Il tuo ragionamento non segue. Sto parlando del suo stato statico (come un dizionario statico/elenco su un campo statico, usato dal metodo statico), dal momento che non può essere controllato dal chiamante. Normalmente i metodi statici sono thread-safe con il semplice trucco di non usare nessuno stato privato ;-p Lo stato di cose come 'ref' o ref-type args * è * controllato dal chiamante, e dovrebbe essere gestito come tale. Allo stesso modo non ha impatto sulle chiamate esterne. L'aspettativa ** è ** lì, altrimenti avresti un ** lotto ** di blocco in quasi tutte le linee del tuo codice C#. –

0

Il problema con metodi non thread-safe è l'accesso simultaneo a risorse condivise come le variabili di istanza. Se un metodo statico solo funziona su dati privati ​​/ locali, è intrinsecamente thread-safe. Tuttavia, non vi è alcuna garanzia che i metodi statici lo facciano - questo deve essere fatto esplicitamente.

Quindi, per un metodo statico thread-safe non può accedere ai membri statici senza utilizzare la sincronizzazione e deve copiare qualsiasi dato ricevuto come input prima di modificarlo.

+0

Perché i dati privati ​​statici per metodi statici sono a rischio di codice? – Dykam

+0

Non parlo di privato come nei membri privati ​​del tipo, ma privato come nel locale. Poiché ogni thread ha il proprio stack in cui sono memorizzate le localizzazioni, queste non sono condivise tra thread diversi e sono quindi intrinsecamente thread-safe. –

0

TLDR; "Ciò significa che i metodi statici sono intrinsecamente thread-safe?" La risposta è No. Le classi con la nota sopra avranno metodi thread-safe statici perché gli ingegneri Microsoft hanno scritto il codice in modo thread-safe, magari usando i lock o altri meccanismi di sincronizzazione dei thread " (citazione tratta da http://odetocode.com/Articles/314.aspx)

Maggiori dettagli

cosa si tratta? Niente, tranne il codice scritto per quella particolare classe.

L'istruzione è una dichiarazione che indica che i programmatori che hanno scritto la classe si sono accertati che tutti i membri statici (metodi e proprietà) siano thread-safe (ma non lo hanno fatto ad esempio per i membri).

L'ho fatto in modo che le statiche siano thread-safe perché, essendo statiche, è molto probabile che vengano richiamate da più thread, quindi inseriscono il lavoro extra necessario per assicurarsi che tutto ciò sia a posto. Spesso i metodi statici sono anche funzioni stateless, il che significa che sono già generalmente thread-safe (non è necessario alcun lavoro aggiuntivo).

Al contrario, per esempio i membri della dichiarazione sono semplicemente loro che ti dicono che non sono stati così attenti con loro.

Spesso le istanze vengono create da un singolo thread e sono accessibili solo da quel thread; se l'istanza non è mai accessibile da più thread, la sicurezza del thread non è un problema, quindi i programmatori non si sono preoccupati di aggiungerlo.

L'istruzione non è un'asserzione relativa a proprietà intrinseche dell'istanza statica vs; entrambi possono essere non sicuri a meno che non si inserisca un codice specifico per garantire che più thread possano accedervi senza problemi (o se, per loro natura, sono già thread-safe, ad esempio una funzione stateless).

È semplicemente una dichiarazione che i programmatori che hanno scritto quelle classi hanno fatto in modo che i membri statici siano sicuri, ma non lo hanno fatto ad esempio per i membri.

Problemi correlati