2012-11-13 10 views
10

Questo può sembrare un po 'pazzo, ma è un approccio che sto considerando come parte di una libreria più grande, se posso essere ragionevolmente certo che non causerà comportamenti strani.Multiplexing C# 5.0 asincrona su un pool di thread - thread-safe?

L'approccio:

codice utente Run asincrona con un SynchronizationContext che invia a un pool di thread. Il codice utente sarebbe simile:

async void DoSomething() 
{ 
    int someState = 2; 
    await DoSomethingAsync(); 
    someState = 4; 
    await DoSomethingElseAsync(); 
    // someState guaranteed to be 4? 
} 

Non sono sicuro se l'accesso al someState sarebbe threadsafe. Mentre il codice verrebbe eseguito in un "thread" in modo tale che le operazioni siano, in effetti, totalmente ordinate, potrebbe comunque essere suddivisa su più thread sotto il cofano. Se la mia comprensione è corretta, l'ordinamento dovrebbe essere sicuro su x86, e poiché la variabile non è condivisa, non dovrò preoccuparmi delle ottimizzazioni del compilatore e così via.

Ancora più importante, tuttavia, sono preoccupato se questo sarà garantito thread-safe sotto i modelli di memoria ECMA o CLR.

Sono abbastanza sicuro di dover inserire una barriera di memoria prima di eseguire un lavoro in coda, ma non sono totalmente sicuro del mio ragionamento qui (o che questo approccio potrebbe non essere utilizzabile per ragioni completamente separate) .

+5

È una variabile locale. Come può non essere infallibile? IOW cosa ti fa pensare che possa essere cambiato in un'altra discussione? (A meno che non stiate passando un riferimento ad esso da qualche parte che non viene mostrato, ad esempio 'ref' o come variabile catturata). – leppie

+3

Da quanto ho capito, 'await' trasforma il seguente codice in una continuazione che viene eseguita sul' SynchronizationContext' corrente quando termina il 'Task' sottostante. Se si sta effettuando la distribuzione in un pool di thread, la continuazione può essere eseguita su un thread diverso. Non funzionerà * contemporaneamente * in alcun modo, ma non sono sicuro che le modifiche a 'someState' sarebbero visibili se la continuazione viene eseguita su un thread fisico diverso. – ShZ

+2

Questa è una grande domanda, che molte persone non sanno nemmeno chiedere. –

risposta

9

Questo è risolta in sezione commenti del async/await FAQ:

TPL comprende le barriere appropriate quando i compiti vengono accodati e all'inizio/fine dell'esecuzione compito in modo che i valori siano adeguatamente resi visibili.

Quindi non sono necessarie barriere esplicite.