0

Windows Azure 用の .NET を使用する WebService があります。そこで、while(true)ループで何かを行うメソッドを持つシングルトンクラスがあります。このメソッドは、シングルトンのインスタンス変数を使用します。新しいスレッドで無限ループを開始します。インスタンス変数の値を (Web サービスを使用して) 変更すると、値が変更されます。ただし、無限ループのスレッドでは古い値が使用されます。コードは次のようになります。

シングルトン クラス

public class Singleton
{
    static Singleton _instance;

    public static Singleton Instance
    {
        get { return _instance ?? (_instance = new Singleton()); }
    }

    private Singleton() {
        this.Intervall = -20;
    }

    public int Intervall { get; set; }

    public void run()
    {
        Thread thread = new Thread(privateRun);
        thread.Start();
    }

    private void privateRun()
    {
        while (true)
        {
            // do something with Intervall Value
            Trace.WriteLine(this.Intervall);

        }
    }
}

WebRole onstart(); で run メソッドを開始します。

public override bool OnStart()
    {
        // start the singleton method
        Singleton singleton= Singleton.Instance;
        singleton.run();

        return base.OnStart();
    }

そして値を WebService から変更します

public string setIntervall(int Intervall)
    {
        Singleton.Instance.Intervall = Intervall;
        return "New Intervall: " + Singleton.Instance.Intervall;
    }

WebService は実際に新しい Intervall を返します。ただし、while ループでは古い値が使用されます。では、作成されたスレッドの値を変更するにはどうすればよいでしょうか?

4

1 に答える 1

4

問題は、デフォルトで、コンパイラ/ランタイムがキャッシュ値を含む多くの最適化を行うことです。これは、スレッド環境では問題になります。各スレッドには独自のキャッシュがあるため、同じ変数を変更していると思っていても同じ変数を変更していないからです。

いくつかの解決策があります。

最初は使用することvolatileです:

private volatile int _interval;
public int Interval
{
    get
    {
        return _interval;
    }
    set
    {
        _interval = value;
    }
}

volatileは、「これは複数のスレッドからアクセスできます。これが変更されたときにキャッシュが同期されていることを確認してください。

もう 1 つは、変数にアクセスするときにメモリ バリアを導入することです。ステートメントはこれを暗黙のlockうちに行いますが、この特定のプログラムの要点はロック フリー プログラミングにあるように見えるため、これは好ましくありません。volatile は、特定のニーズにより適しています。

于 2013-01-02T18:04:47.757 に答える