5

VB.Net does not have an equivalent of C# volatile keyword so you have to manually implement volatile which is usually done by calling Thread.MemoryBarrier() before read and after write. So something like this is equivalent to declaring C# volatile variable:

    ''' <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

I am wondering of the memory barrier before read is necessary if the only place where I write to the variable is through a setter and there I always call Thread.MemoryBarrier() after the write.

Can I safely remove the Thread.MemoryBarrier() before read?

Edit: To make it more clear I am asking if I can remove the Thread.MemoryBarrier() before read in order to remove costs of memory fence for each read.

Dalibor Čarapić
  • 2,792
  • 23
  • 38
  • 2
    The [`Volatile` class](http://msdn.microsoft.com/en-us/library/system.threading.volatile(v=vs.110).aspx) should work in VB.net and the `Thread` class contains methods like [`VolatileRead`](http://msdn.microsoft.com/en-us/library/zdxzk5cw.aspx) – CodesInChaos Jan 14 '15 at 09:04
  • The question is can I safely remove the Thread.MemoryBarrier() before read to avoid potentially unnecessary cost of memory fence on reads. – Dalibor Čarapić Jan 14 '15 at 09:17
  • I'm pretty sure that you can get stale reads if you remove it. – CodesInChaos Jan 14 '15 at 09:21
  • 2
    You can't remove it. Pretty unlikely you are using it correctly when you ask this question btw. [Read this](http://stackoverflow.com/a/27469253/17034). – Hans Passant Jan 14 '15 at 09:40
  • Well the internet is a bit conflicting here then. Please look at: http://www.albahari.com/threading/part4.aspx (excerpt: The static VolatileRead and VolatileWrite methods in the Thread class read/write a variable while enforcing (technically, a superset of) the guarantees made by the volatile keyword. Their implementations are relatively inefficient, though, in that they actually generate full fences) – Dalibor Čarapić Jan 14 '15 at 09:59

1 Answers1

2

You can't remove the barrier on the read-side which is easy to show by example. Let's use this reader:

while (!IsDisposed); //reads _isDisposed

The value of _isDisposed can clearly be cached in a register here so that new writes will never become visible. This loop could be infinite (for example - other effects are possible such as long delays).

More formally, the reads of _isDisposed can all move "upwards" in time to appear to run before the store happens. volatile stores effect a release fence meaning that nothing can move over them later in time. Things can move over them to previous points in time, though.

Use the Volatile class. Or, use a struct written in C# as a wrapper around the field:

struct VolatileInt32Box { public volatile int Value; }
usr
  • 168,620
  • 35
  • 240
  • 369
  • I will use the VolatileRead/VolatileWrite solution as proposed by Hans Passant. – Dalibor Čarapić Jan 14 '15 at 13:50
  • @dcarapic for some reason those two methods are much slower. They compile to method calls. They have only disadvantages. – usr Jan 14 '15 at 14:08
  • Not according to Hans pasant (link that he provided http://stackoverflow.com/questions/27468923/best-way-to-implement-thread-safe-atomic-accessors-of-a-long-property-on-a-guara/27469253#27469253). Now I have not tested this but I have read from other sources that C# volatile keyword and VolatileWrite/VolatileRead should be similar in functionality and speed. – Dalibor Čarapić Jan 14 '15 at 18:04
  • I have tested this a few days ago on the current 4.5 JIT and the next gen RyuJIT. RyuJIT generates good code, the current JIT continues to disappoint. Disregarding performance I recommend: Use the newer functionality (the Volatile class). – usr Jan 14 '15 at 19:01