2012-02-09 12 views
7

Eventuali duplicati:
Are C# arrays thread safe?Più thread di accesso stesso array multidimensionale

mi sono stati di programmazione C# per 10 mesi. Ora sto imparando il multi-threading e sembra funzionare bene. Ho un array multi-dimensionale come

string[,] test = new string[5, 13]; 

Ho i metodi di chiamata dei thread che finiscono per salvare i loro output su coordinate diverse all'interno dell'array sopra. senza scrivere un thread nella stessa posizione di un altro thread.

Così Thread1 potrebbe scrivere a test[1,10] ma nessun altro thread sarà mai scrivere a test[1,10]

La mia domanda è: ho letto su come utilizzare le serrature su oggetti come il mio array, devo preoccuparsi affatto sui blocchi anche se i miei thread potrebbero accedere allo stesso array di test contemporaneamente ma non scrivere mai le stesse coordinate (posizione di memoria)?

Finora nei test non ho avuto problemi, ma se qualcuno più esperto di me sa che potrei avere problemi allora cercherò di usare le serrature.

+1

No, non è necessario il blocco nello scenario illustrato. Ma presumo che tu stia leggendo i dati ad un certo punto? Aspetti fino a quando tutti i tuoi thread hanno finito prima di iniziare a leggere? – Douglas

+1

Se non si utilizzano i blocchi, sarebbe consigliabile introdurre una barriera di memoria (chiamando 'Thread.MemoryBarrier()') prima di iniziare a leggere, in modo da garantire che tutti i thread abbiano accesso ai dati 'freschi'. [Sincronizzazione non bloccante] (http://www.albahari.com/threading/part4.aspx) ha una grande spiegazione su questo concetto. – Douglas

+0

grazie, i thread sono generati da un singolo thread master, scrivono solo i dati sull'array, quindi, una volta che tutti terminano, RunWorkerCompleted dal thread master, legge l'array. quindi penso di essere al sicuro, grazie per la spiegazione. –

risposta

7

Se è possibile garantire che due thread non tenteranno mai di leggere o scrivere sullo stesso elemento, non è necessario eseguire alcun blocco e se si aggiunge il blocco, il codice verrà rallentato.

Si dovrebbe tuttavia dedicare del tempo ad aggiungere commenti appropriati per spiegare che, (e possibilmente perché) nessun thread acceda mai agli stessi elementi per evitare problemi futuri che Jim Fell ha menzionato nella sua risposta.

Aggiornamento: molti degli altri poster continuano a suggerire che il blocco debba essere usato solo come salvaguardia dagli errori dei futuri sviluppatori. A tal fine, dipende davvero dalla tua applicazione. Se le prestazioni non sono un problema, assicurati di andare avanti e sincronizzare l'accesso agli elementi.

Tuttavia, la maggior parte delle volte in cui più thread accedono a un singolo array, la ragione per cui esistono più thread è eseguire l'elaborazione parallela su grandi quantità di dati in cui le prestazioni rappresentano un problema significativo. Se non fosse una preoccupazione, potreste semplicemente usare un singolo thread e essere molto più a suo agio sul fatto che non venga incasinato da altri. In tali prestazioni, l'affidabilità del lock (in varie forme) è, di norma, minimizzata quando possibile. La sincronizzazione attraverso la separazione dei dati (che impedisce loro di leggere/scrivere sempre nelle stesse posizioni di memoria) è di gran lunga superiore all'utilizzo dei blocchi, quando è fattibile.

0

È necessario utilizzare le istruzioni di blocco per garantire che il proprio oggetto dati sia sicuro per i thread. Potrebbe funzionare ora, ma in seguito (specialmente quando/se il codice viene aggiornato) tu (o il tuo sostituto) potresti imbatterti in sfuggenti bug di corruzione o di corruzione dei dati. Check out this article on the MSDN website. Ha un bell'esempio su come utilizzare le istruzioni di blocco.

1

Una cosa da tenere a mente è se si esegue un test con un processore single core, tutto potrebbe funzionare correttamente, ma non appena si esegue un processore multi-core, si incontrano problemi con i thread che colpiscono un pezzo condiviso di memoria allo stesso tempo.

Giusto per essere sicuri, se i due thread stanno effettivamente modificando direttamente il multi-array, è necessario implementare un sistema di blocco. This answer in StackOverflow ha un buon esempio di blocco.

-1

I blocchi servono solo a impedire l'accesso simultaneo. Quindi se lo garantisci in altro modo, non hai bisogno di serrature.

P.S. Suppongo che tu abbia assegnato ciascun thread a ciascun elemento dell'array, giusto?

+4

L'accesso simultaneo è solo un problema se le operazioni simultanee sono sia * mutanti * che * non atomiche *. Ma le serrature fanno di più che fare operazioni non atomiche in operazioni atomiche; introducono anche * barriere di memoria full-fence *. Supponiamo che l'autore del codice garantisca intelligentemente che non saranno intercalate due letture/scritture di memoria non atomiche; è grandioso, ma farlo potrebbe essere insufficiente. ** Fare così non è una garanzia che due thread abbiano una vista * coerente * di tutte le mutazioni su tutti i dati **. –

+0

Ha detto che ogni thread funziona con il proprio elemento dell'array. L'ordine non importa qui. – Dims

+2

Non stai seguendo il mio punto. Supponiamo che il thread Alpha scriva 123 nella posizione dell'array 2. Supponiamo che Bravo abbia la garanzia di non leggere la posizione 2 fino a quando il thread Alpha non ha terminato la mutazione, tramite una soluzione non bloccante. Che garanzia c'è che quando thread Bravo legge la posizione 2, trova 123 in quella posizione? Assolutamente no! Thread Bravo potrebbe essere in esecuzione su un processore diverso rispetto al thread Alpha e ** Il processore di Bravo potrebbe avere una cache nella pagina di memoria dell'array. ** Cosa costringe la CPU di Bravo a invalidare la cache? *Niente*. –

Problemi correlati