Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do both c# and java's volatile keyword behave the same way?

I know in java, if you have multiple threads accessing a variable that isn't marked as volatile, you could get some unexpected behavior.

Example:

private boolean bExit;

 while(!bExit) {
    checkUserPosition();
    updateUserPosition();
 }

If you mark the bExit variable as voilatile, that would gaurantee that other threads will see the most recent value.

Does c# behave the same way?

Update

For example, in C# if you do this:

int counter = ...;

for(...)
{
   new Thread(delegate()
   {

      Interlocked.Decrement(ref counter);
   }
}


if(counter == 0) 
{
   // halt program
}

In the above, in c#, do you have to mark the counter variable as volatile or this will work as expected?

like image 269
loyalflow Avatar asked May 01 '13 20:05

loyalflow


1 Answers

You need to be a bit careful here as you've chosen two different types in your examples. My general rule of thumb is that volatile is best used with booleans and with everything else you probably need some other kind of sync'ing mechanism. It's very common in C# and java to use a volatile boolean to e.g. stop a loop or task executing which has visibility from multiple threads:

class Processor
{
    private volatile Boolean _stopProcessing = false;

    public void process()
    {
        do
        { ... }
        while (!_stopProcessing);
    }

    public void cancel()
    {
        _stopProcessing = true;
    }
}

The above would work in C# or java and in this example the volatile keyword means that the read in the process method will be from the actual current value and not a cached value. The compiler or VM may choose to otherwise allow the value to be cached as the loop in process doesn't change _stopProcessing itself.

So the answer is yes to your first question.

Whilst you can use volatile on an int this only helps if you're only ever reading, or writing a single value. As soon as you do anything more complex, e.g. incrementing, you need some other kind of sync'ing such as your usage of Interlocked. In your second example however you are still reading the value of counter without any sync'ing so you're effectively relying on other usages of counter to be sync'ed (e.g. with Interlocked).

In your second example you would still be better off marking your int as volatile, this way you again can be sure that you're getting the current value and not some cached version. However using volatile alone is not enough because the read at the bottom could overlap with a standard decrement (counter--) rather than your correct use of Interlocked.

like image 132
Matt Avatar answered Oct 20 '22 18:10

Matt