Do properties have volatile effect?

后端 未结 6 1720
無奈伤痛
無奈伤痛 2021-02-19 10:54

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

相关标签:
6条回答
  • 2021-02-19 11:13

    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.

    0 讨论(0)
  • 2021-02-19 11:15

    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.

    0 讨论(0)
  • 2021-02-19 11:17

    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.

    0 讨论(0)
  • 2021-02-19 11:18

    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.

    0 讨论(0)
  • 2021-02-19 11:23

    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.

    0 讨论(0)
  • 2021-02-19 11:24

    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.

    0 讨论(0)
提交回复
热议问题