属性有波动效应吗?

sht*_*iha 12 c# concurrency multithreading

在下面的代码将read1始终等于read2,提供的属性Flag可以从其他线程更改?这里关注的是Flag可能会内联.

private bool Flag {get; set;}

public void MultithreadedMethod()
{
    var read1 = Flag;

    /* some more code */

    var read2 = Flag;    
}
Run Code Online (Sandbox Code Playgroud)

UPD:其他一些线程Flag/* some more code */执行期间可能会改变其值.在这种情况下read1应该是不同的read2.它将永远是这样吗?不会内联将属性变成一个非易失性字段,尽管事实上读取之间已经改变了,但这将导致read1等于read2Flag

Tud*_*dor 16

不,财产不是volatile.

虽然我无法为您的初始场景获得令人满意的演示,但这种替代方法应该很好地证明了这个陈述:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

在Release模式下构建它将使程序死锁,从而证明Flag它没有volatile行为(即它在读取之间得到"优化").

更换public bool Flag { get; set; }public volatile bool Flag;会使程序正确终止.

  • 另一种可能性是使支持字段易变.所以你仍然可以像内部一样使用相同的set修饰符. (3认同)
  • 封装的易变场怎么样?私人波动布尔旗; 和财产标志{get {return flag; },设置{flag = value; }? (3认同)
  • @ILIA BROUDNO:这个例子取决于环境,尽管只要你有一台多核机器,它就应该在.Net版本中相当一致.我刚刚在VS 2013,四核Xeon上的.Net 4.5中进行了测试,我仍然可以重现它.确保在构建项目属性时在项目属性中启用"优化代码". (2认同)