views:

820

answers:

4

The following code

using System.Threading;

class Test
{
    volatile int counter = 0;
    public void Increment()
    {
     Interlocked.Increment(ref counter);
    }
}

Raises the following compiler warning:

"A reference to a volatile field will not be treated as volatile"

Am I doing something wrong here to raise this warning? Why does the compiler me warn about this?

+1  A: 

You're getting the error because you're passing the field by reference. I think what this means is that the target method has no idea the field is marked as volatile, and therefore will not treat it as such.

HTH, Kent

Kent Boogaart
+7  A: 

Basically the warning is that when you pass a volatile field by reference, the calling code doesn't know to treat it in a volatile manner. For Interlocked.Increment that probably doesn't matter, due to the nature of the method - but then you don't need the variable to be volatile anyway if you're using Interlocked.

In general, I think I'd avoid mixing the two - if you're using Interlocked, do it everywhere (using Interlocked.CompareExchange(ref counter, 0, 0) to read it). I can't say I use volatile very often, personally. For simple counters I might use Interlocked, but I'm more likely to use a lock for most tasks.

Jon Skeet
You are getting me confused. In a previous question (395232) I understood from your answer that I needed both Interlocked and volatile. Now you say "you don't need the variable to be volatile anyway if you're using Interlocked."
Jader Dias
No, they're alternatives to each other: "Or preferably use Interlocked, a volatile variable, or a lock." That was meant to give three *different* approaches, not a combined one. Was that the part which was misleading you?
Jon Skeet
I understand that in a multiprocessor enviroment, multiple caches can make one processor increment one cached value that isn't the last value. In that case, as far as I know, a Interlocked won't help, cause it does not creates the MemoryBarrier that is needed to refresh the caches.
Jader Dias
One question, do you visit every question you answered to check if anyone has commented, or you have some sort of RSS that alerts you?
Jader Dias
I read the "Responses" tab of my user page.
Jon Skeet
Thanks, I'm new to SO, so I didn't knew of the "Responses" tab. Btw could you please answer my previous comment? (The third comment in this answer counting from top)
Jader Dias
Interlocked does everything required to make it right - memory barriers, atomicity etc. It would be useless without this.
Jon Skeet
+5  A: 

You are not doing anything wrong. According to the documentation:

A volatile field should not normally be passed using a ref or out parameter, since it will not be treated as volatile within the scope of the function. There are exceptions to this, such as when calling an interlocked API.

Darin Dimitrov
I'd say that the Interlocked methods still aren't treating it any differently to how they'd treat any other field - it's just that *all* fields are handled in a special way by Interlocked.
Jon Skeet
A: 

Use this:

        #pragma warning disable 420
        if(Interlocked.CompareExchange(ref isLoaded, 1, 0) != 0)
            return;
        #pragma warning restore 420
Robert Fraser
nice ascii artwork, but it doesn't answers the question
Jader Dias