9

マルチスレッドのWinサービスでシングルトンを使用してロギングを行うことを検討しており、発生する可能性のある問題のいくつかを知りたいと思っていました。同期を処理するためのgetインスタンスをすでに設定しています

    private static volatile Logging _instance;
    private static object _syncRoot = new object();

    private Logging(){}
    public static Logging Instance
    {
        get
        {
            if (_instance==null)
            {
                lock(_syncRoot)
                {
                    if (_instance == null)
                    {
                        _instance = new Logging();
                    }
                }
            }
            return _instance;
        }
    }

他に心配する必要があることはありますか?

4

8 に答える 8

13

それは私にはかなり良さそうです。

詳細については、C# でのシングルトン パターンの実装を参照してください。

編集:ただし、おそらくリターンをロック内に配置する必要があります。

于 2009-04-07T17:04:04.807 に答える
12

これは何よりも情報提供です。

あなたが投稿したのは二重チェックされたロック アルゴリズムです。私が知る限り、あなたが投稿したものは機能します。(Java 1.5 の時点では、そこでも動作します。) ただし、これは非常に脆弱です。少しでも間違えると、非常に微妙な競合状態が発生する可能性があります。

私は通常、静的初期化子でシングルトンを初期化することを好みます。

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

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

    private Singleton()
    {
        // Do stuff
    }
}

(少し余分な遅延が必要な場合は、静的コンストラクターを追加してください。)

そのパターンの方が簡単にうまくいくし、ほとんどの場合、うまくいく。

私のC# シングルトン実装ページ(Michael もリンクしています)に詳細があります。

危険性については、最大の問題はテスト可能性を失うことだと思います。おそらくロギングにはそれほど悪くはありません。

于 2009-04-07T17:16:39.160 に答える
3

シングルトンは、クラスによって具体化されたリソースへのアクセスのボトルネックになる可能性があり、そうでなければ並行して使用される可能性のあるリソースへの順次アクセスを強制します。

この場合、それは悪いことではないかもしれません。なぜなら、複数のアイテムが同時にファイルに書き込まれることを望まないからです。それでも、実装がその結果になるとは思いません。しかし、それは注意すべきことです。

于 2009-04-07T17:06:15.660 に答える
2

ロガーの各メソッドが同時に実行しても安全であることを確認する必要があります。つまり、適切なロックなしで共有状態に書き込まないようにする必要があります。

于 2009-04-07T17:55:58.147 に答える
1

アンチパターンと見なされるものをダブルチェックロックを使用しています。ウィキペディアには、さまざまな言語の遅延初期化がある場合とない場合のパターンがあります。

シングルトンインスタンスを作成した後は、もちろん、すべてのメソッドがスレッドセーフであることを確認する必要があります。

于 2009-04-07T17:08:26.390 に答える
1

より良い提案は、シングルスレッドのセットアップ手順でロガーを確立することです。これにより、必要なときにそこにあることが保証されます。Windows サービスでは、OnStart はこれを行うのに最適な場所です。

別のオプションは、 System.Threading.Interlocked.CompareExchange(T%, T, T) : T メソッドを使用して切り替えることです。混乱が少なく、動作することが保証されています。

System.Threading.Interlocked.CompareExchange<Logging>(_instance, null, new Logging());
于 2009-04-07T17:17:14.730 に答える
1

二重チェック ロック パターンを使用し、それをすべてのメモリ モデルで動作させたい場合は、null の最初のチェックで Thread.VolatileRead() を使用する必要があることについては、いくつかの議論があります。議論の例はhttp://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/b1932d46-877f-41f1-bb9d-b4992f29cedc/で読むことができます。

そうは言っても、私は通常、上記のJon Skeetのソリューションを使用します。

于 2009-04-28T22:50:41.543 に答える
0

Loggingインスタンスメソッドがスレッドセーフであれば、心配する必要はないと思います。

于 2009-04-07T17:04:45.790 に答える