2015-01-14 22 views
5

VB.Net non ha un equivalente di parola chiave volatile C#, quindi è necessario implementare manualmente volatile che viene in genere eseguito chiamando Thread.MemoryBarrier() prima di leggere e dopo la scrittura. Quindi, qualcosa di simile è equivalente a dichiarare C# variabile volatile:VB.NET: Devo chiamare Thread.MemoryBarrier() prima di ogni lettura se completo sempre le mie scritture con Thread.MemoryBarrier()?

''' <summary> 
    ''' Gets a value indicating whether this instance is disposed. 
    ''' </summary> 
    Public Property IsDisposed As Boolean 
     Get 
      Threading.Thread.MemoryBarrier() 
      Return _isDisposed 
     End Get 
     Private Set(value As Boolean) 
      _isDisposed = value 
      Threading.Thread.MemoryBarrier() 
     End Set 
    End Property 

mi chiedo della barriera memoria prima lettura è necessaria se l'unico posto dove scrivo alla variabile è attraverso un setter e ci ho sempre chiamare Discussione .MemoryBarrier() dopo la scrittura.

Posso rimuovere in modo sicuro il Thread.MemoryBarrier() prima di leggere?

Modifica: per rendere più chiaro mi chiedo se posso rimuovere il Thread.MemoryBarrier() prima di leggere al fine di rimuovere i costi della recinzione di memoria per ogni lettura.

+2

Il [classe 'Volatile'] (http://msdn.microsoft.com/en-us/library/system.threading.volatile (v = vs.110) .aspx) dovrebbe funzionare in VB.net e la classe 'Thread' contiene metodi come [' VolatileRead'] (http://msdn.microsoft.com/en-us/library/zdxzk5cw.aspx – CodesInChaos

+0

La domanda è possibile rimuovere il Thread.MemoryBarrier() prima di leggere in modo sicuro per evitare costi potenzialmente inutili della recinzione di memoria su letture. –

+0

Sono abbastanza sicuro che è possibile ottenere letture stantio se si rimuove. – CodesInChaos

risposta

2

Non è possibile rimuovere la barriera sul lato di lettura che è facile da mostrare con l'esempio. Usiamo questo lettore:

while (!IsDisposed); //reads _isDisposed 

Il valore di _isDisposed può chiaramente essere memorizzati nella cache in un registro qui in modo che le nuove scritture non diventeranno mai visibile. Questo ciclo potrebbe essere infinito (per esempio - altri effetti sono possibili come lunghi ritardi).

Più formalmente, le letture di _isDisposed possono tutte spostarsi "in alto" nel tempo in modo che sembrino essere eseguite prima che si verifichi lo store. I negozi volatile producono un recinto di rilascio che significa che nulla può spostarsi su di loro più tardi nel tempo. Le cose possono spostarle su punti precedenti nel tempo, però.

Utilizzare la classe Volatile. In alternativa, utilizzare una struttura scritta in C# come un involucro intorno al campo:

struct VolatileInt32Box { public volatile int Value; } 
+0

Userò la soluzione VolatileRead/VolatileWrite come proposto da Hans Passant. –

+0

@dcarapic per qualche ragione questi due metodi sono molto più lenti. Si compilano per le chiamate di metodo. Hanno solo degli svantaggi. – usr

+0

Non secondo Hans pasant (link che ha fornito http://stackoverflow.com/questions/27468923/best-way-to-implement-thread-safe-atomic-accessors-of-a-long-property-on-a -guara/27469253 # 27469253). Ora non ho provato questo, ma ho letto da altre fonti che C# volatile keyword e VolatileWrite/VolatileRead dovrebbero essere simili per funzionalità e velocità. –