13

以下のコードではread1、 は常に と等しくなりますがread2、提供されるプロパティFlagは他のスレッドから変更できますか? ここでの懸念は、Flagインライン化される可能性があることです。

private bool Flag {get; set;}

public void MultithreadedMethod()
{
    var read1 = Flag;

    /* some more code */

    var read2 = Flag;    
}

UPD : 実行中に他のスレッドがFlagの値を変更する可能性があります/* some more code */。この場合read1、 とは異なるはずread2です。それは常にそうでしょうか?インライン化すると、読み取り間で事実が変更されread1read2にもかかわらず、プロパティが非揮発性フィールドに変わりませんか?Flag

4

6 に答える 6

17

いいえ、物件は ではありません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();
    }
}

これをリリース モードでビルドすると、プログラムがデッドロック状態になるため、Flag揮発性の動作がないことが証明されます (つまり、読み取り間で「最適化」されます)。

に置き換えるpublic bool Flag { get; set; }public volatile bool Flag;、プログラムが正しく終了します。

于 2012-05-29T10:28:05.147 に答える
1

autoproperty の volatile の欠如は残念です。[StructLayout(LayoutKind.Sequential, Pack = 4)] および Marshal.PtrToStructure で構造体を使用する場合、autoproperty を使用すると期待どおりにバイト レイアウトが保持されないことがわかりました。私がしたことは、プライベート バッキング フィールドを使用し、最後にプロパティを配置することでした。

于 2012-10-23T09:59:35.010 に答える
1

他の回答を要約すると、この状況では、コードの実行後に 2 つの変数の値がどうなるかは予測できません。CLR とコンパイラは私たちにとって大部分がブラック ボックスであり、競合状態の結果に関するあらゆる種類の予測は、ある時点で間違いにつながるギャンブルであるためです。

とにかく、マルチスレッド環境でこの種のコードを書くことはできません。

于 2012-05-29T09:58:21.087 に答える