13

In the code below will read1 be always equal to read2, provided property Flag can be changed from other threads? Concern here is that Flag may get inlined.

private bool Flag {get; set;}

public void MultithreadedMethod()
{
    var read1 = Flag;

    /* some more code */

    var read2 = Flag;    
}

UPD: Some other thread may change Flag's value during /* some more code */ execution. In this case read1 should be different from read2. Will it always be the case? Won't inlining turn the property into an non-volatile field that will cause read1 to be equal to read2 despite tha fact Flag was changed between reads?

shtriha
  • 283
  • 3
  • 9
  • I see no reason that it would be *guaranteed*. Of course, `volatile` also doesn't typically have quite the meaning people think. Personally I'd look at a `lock` or `Interlocked` if it matters. – Marc Gravell May 29 '12 at 10:15

6 Answers6

19

No, the property is not volatile.

While I have not been able to obtain a satisfactory demonstration for your initial scenario, this alternative method should prove the statement nicely:

class Program
{
    public bool Flag { get; set; }

    public void VolatilityTest()
    {
        bool work = false;
        while (!Flag)
        {
            work = !work; // fake work simulation
        }
    }

    static void Main(string[] args)
    {
        Program p = new Program();
        var t = new Thread(p.VolatilityTest);
        t.Start();
        Thread.Sleep(1000);
        p.Flag = true;
        t.Join();
    }
}

Building this in Release mode will make the program deadlock, hence proving that Flag does not have volatile behavior (i.e. it gets "optimized" between reads).

Replacing public bool Flag { get; set; } with public volatile bool Flag; will make the program terminate correctly.

Tudor
  • 61,523
  • 12
  • 102
  • 142
  • 4
    An other possibility is to make the backing field volatile. So you can still use same set modifier like internal. – 0xBADF00D Apr 16 '13 at 09:11
  • 3
    What about an encapsulated volatile field? private volatile bool flag; and a Property Flag { get { return flag; } , set { flag = value; } } ? – Pedro77 Sep 03 '14 at 13:23
  • 1
    Very interesting point but in my test the Release version of your exact code did not lock. Running in Visual Studio 2013 in a new Console project so the optimization settings are whatever the default is. I get that it is implementation dependent whether it gets optimized away or not, but I am having a hard time believing that a variable's actual value will not be checked in while (!Flag) and instead its initial value be used. Especially when the compiler can determine that the value does change. – ILIA BROUDNO Oct 19 '15 at 18:34
  • 2
    @ILIA BROUDNO: This example depends on the environment, although it should be fairly consistent across .Net versions as long as you have a multi-core machine. I just tested this in VS 2013, .Net 4.5 on a Quad-Core Xeon and I can still reproduce it. Make sure "optimize code" is enabled in the project properties when building it. – Tudor Oct 20 '15 at 09:03
  • 1
    @Tudor: Thanks for checking. On my end - Visual Studio 2013 .Net 4.5 quad core i5. Optimize code is checked. Not locking. – ILIA BROUDNO Oct 20 '15 at 18:41
3

Yes it can be changed naturally.

Even in the code provided it's not guranteed that read1 would be equal to read2.

Considering that meanwhile /* some more code */ executed, Flag can be affected by other threads.

EDIT

The equality of read1 and read2 has nothing to do with inlining or not, Flag is a bool, so it's a value type. So

  • var read1 = Flag; //let's say read1 TRUE
  • Flag = False
  • var read2 = Flag; //read2 is FALSE, but read1 remains TRUE

This is valid in non multithreaded environment too, cause you operating on value type.

If this is not what you're asking for, please clarify.

Tigran
  • 61,654
  • 8
  • 86
  • 123
  • I think given the OPs edit, he's asking that assuming a thread changes `Flag` while `/* some more code */` is being executed, is it **guaranteed** that `read2` will pick up on this change. – George Duckett May 29 '12 at 09:52
2

The lack of volatile for an autoproperty is disappointing. I discovered that when using a struct with [StructLayout(LayoutKind.Sequential, Pack = 4)] and Marshal.PtrToStructure the byte layout is not preserved as expected if an autoproperty is used. What I did was use private backing fields and put the properties at the end.

Steed
  • 287
  • 3
  • 15
1

if Flag can be changed from other threads, there is no guarantee that read1 and read2 will be the same. You would have to use a monitor/mutex surrounding your code and also make sure that the Flag setter also respects that mutex.

Dirk Trilsbeek
  • 5,873
  • 2
  • 25
  • 23
  • Yes but is there guarantee that read1 and read2 will be different. – shtriha May 29 '12 at 09:31
  • a guarantee that they will be different? Of course not. They might be different, depending on the running code alongside with your code in MultithreadedMethod. If there is another thread manipulating Flag, they could be different. – Dirk Trilsbeek May 29 '12 at 09:35
1

To sum up the other replies, in this situation, what happens to the values of the two variables after the code is executed can't be predicted. Both because the CLR and compiler are largely black boxes to us, and because any sort of prediction regarding the outcome of a race condition is really a gamble that's bound to be wrong at some point.

Regardless, you cannot write code of this sort in a multi-threaded environment.

GregRos
  • 8,667
  • 3
  • 37
  • 63
-1

According to the documentation

The volatile keyword indicates that a field can be modified in the program by something such as the operating system, the hardware, or a concurrently executing thread. ... Using the volatile modifier ensures that one thread retrieves the most up-to-date value written by another thread.

ABH
  • 3,391
  • 23
  • 26
  • 1
    What about about auto-property?. It can't be done volatile. But will it behave as volatile? – shtriha May 29 '12 at 09:44
  • 3
    Auto-properties declare a private field of the same type as the property and access it through the getter and setter. The private properties doesn't have any special modifiers, so it won't behave like a volatile field. – Wormbo May 29 '12 at 10:46
  • Too bad you can’t use `volatile` on an autoproperty to cause the underlying field to be `volatile`. Sorry, your answer doesn’t answer the question, only your comments do ;-). – binki Jul 13 '16 at 14:19