-1

私はこのコードを持っています:

public class Singleton
{
    private static Singleton m_instance;
    private Singleton()
    {    

    }

    public static Singleton Instance
    {
        get
        {
            if (m_instance == null)
            {
                m_instance = new Singleton();
            }
            return m_instance;
        }
    }

    public void CallMe()
    {
       // is this function thread safe ? 
    }
}

すべてのインスタンス メンバー関数がスレッド セーフであるため、CallMe メソッドはスレッド セーフですか? または、ここで例外が発生しますか? ロックを使用したシングルトン コードのサンプルを 1 つ見ましたが、それは本当に必要ですか?

4

6 に答える 6

3

ここには複数の問題があります...

まず、Instance プロパティは必ずしもスレッド セーフであるとは限りません。

2 つのスレッドが同時にプロパティを要求すると、両方ともm_instance== null to betr​​ue` を同時に見つけることができ、Singleton の 2 つの異なるインスタンスを返すことができますが、将来の呼び出しに割り当てられるのは 1 つだけになります。

実装をする必要があります

private static lockObject lock = new Object();

public static Singleton Instance
{
    get
    {
      if (m_instance != null) return m_instance;
      lock (lockObject)
            {
                if(m_instance != null) return m_instance;
                return m_instance = new Singleton();
            }
    } 
}

または、静的コンストラクターで m_instance をインスタンス化するだけです。

第 2 に、最初の問題が解決された後でも、CallMe() がスレッド セーフであるとは言えません。それが何をしているのかわかりません。

于 2013-08-05T14:47:22.720 に答える
2

まず、あなたのInstanceメソッドはスレッドセーフではありません。同時に 2 回呼び出されると、2 つの異なるインスタンスが返されます (したがって、シングルトン パターンが壊れます)。

そのコードを見なければ、CallMeスレッドセーフかどうかを知ることは不可能です。

于 2013-08-05T14:49:24.680 に答える
1

二重ロックまたはネストされたクラスを持つシングルトーン バリアントがあります。しかし、.NET 4.0 以降で最も簡単な解決策は、Lazy プロパティを使用することです。

public class Singleton
{
    private static Lazy<Singleton> m_instance = new Lazy = new Lazy<Singleton>();
    private Singleton()
    {    

    }

    public static Singleton Instance
    {
        get
        {
            return m_instance.Value;
        }
    }

    public void CallMe()
    {
       // now its threadsafe
    }
}

Lazy コンストラクターは、オプションで作成関数、またはLazyThreadSafetyMode列挙型も受け取ります。

Singleton.Instanceスレッドセーフになりましたが、CallMe()それ自体ではありません。異なるスレッドから呼び出すこともでき、たとえば、他のクラスのフィールドやプロパティにアクセスすることもできます。メソッドがシングルトン インスタンスにあるかどうかは関係ありません。ここでスレッドの安全性を確保するには、他のメカニズムを使用する必要があります。

于 2013-08-05T14:51:17.717 に答える
1

同期のないコードは、ロック メカニズムがなければスレッド セーフではありません。スレッドセーフなコードは、同期メカニズムを持つコードだけです。

于 2013-08-05T14:37:56.933 に答える
0

CallMe をスレッド セーフにする方法は次のとおりです。

public class Singleton
{
    private static readonly Singleton instance = new Singleton();

    private Singleton()
    {    

    }

    public static Singleton Instance { get { return instance; } }

    public void CallMe()
    {
       // Thread Safe
    }
}

言い換えれば、ロック、ミューテックス、および揮発性のものをコアフレームワークに管理させます。

于 2013-08-05T14:59:11.667 に答える