11

C#マルチスレッドプログラムで不正な動作が発生しています。私の静的メンバーの一部は他のスレッドで値を失っていますが、同じ宣言型の一部の静的メンバーは値を失っていません。

public class Context {
  public Int32 ID { get; set; }
  public String Name { get; set; }

  public Context(Int32 NewID, String NewName){
      this.ID = NewID;
      this.Name = NewName;
  }
}

public class Root {
    public static Context MyContext;
    public static Processor MyProcessor;

   public Root(){
     Root.MyContext = new Context(1,"Hal");

     if(Root.MyContext.ID == null || Root.MyContext.ID != 1){
         throw new Exception("Its bogus!") // Never gets thrown
     }

     if(Root.MyContext.Name == null || Root.MyContext.Name != "Hal"){
         throw new Exception("It's VERY Bogus!"); // Never gets thrown
     } 

     Root.MyProcessor = new MyProcessor();
     Root.MyProcessor.Start();
   }
}

public class Processor {
   public Processor() {
   }

   public void Start(){
      Thread T= new Thread (()=> {

          if(Root.MyContext.Name == null || Root.MyContext.Name != "Hal"){
                throw new Exception("Ive lost my value!"); // Never gets Thrown
          }

          if(Root.MyContext.ID == null){
              throw new Exception("Ive lost my value!"); // Always gets thrown
          }

      });
   }
}

これは、特定のタイプの静的メンバーを使用しているときのスレッドミューテーションの問題ですか?

4

3 に答える 3

13

volatileInterlockedを使用して変数を使用するか、代わりにアクセスします。

あなたが遭遇する問題は、コンパイラー(およびネイティブコンパイラー)が、変数がなくても適切であると考えるように、変数へのアクセスを自由に最適化できることです。したがって、彼は変数をレジスターにダンプし、それを再読み取りしない場合があります。

これを回避するには、変数が実際に読み取られていることを確認する必要があります。Volatileはそれを行います。Interlockedもそれを行います(そして、増分/追加などがアトミックに発生することを可能にします)。

どちらを決めるのが良いでしょう。どちらも、プロセッサにメモリバリアを強制しますが、頻繁に実行すると、取るに足らないコストがかかります。私が定期的に使用するパターンの1つは、これらのオブジェクトをほとんど読み取り専用にすることです。これにより、ルートオブジェクト(1つのメモリバリア)のみを置き換えます。メモリバリアを手動で処理する(可能性があります。キーワードのマニュアルを読む)ことは、正しく行うのが面倒です。ただし、これははるかに効率的です。そこで行う量などによっては、必要になる場合があります。

于 2012-12-18T19:30:42.333 に答える
3

volatile複数のスレッドから変更/アクセスされる変数に修飾子を使用してみてください

于 2012-12-18T19:26:20.253 に答える
2

マルチスレッドアプリケーションの共有変数の値は非決定論的です!ロジックでの衝突を避けるために、共有リソースのそれぞれにロックを使用する必要があります。

    static Readonly Object _lock=new Object();
    lock(_lock)
    {
    //accessing your shared variable
    }
于 2012-12-18T19:42:32.397 に答える