4

次のどのコードが最適か疑問に思っています。

private static volatile OrderedDictionary _instance;
private static readonly Object SyncLock = new Object();

private static OrderedDictionary Instance
{
     get { return _instance ?? (_instance = new OrderedDictionary()); }
}

 public static Mea Add(Double pre, Double rec)
{
     lock (SyncLock)
     {
        ...
     }
}

それとも、IMOは次のものを使用するだけで問題ありませんか?

private static volatile OrderedDictionary _instance;

private static OrderedDictionary Instance
{
     get { return _instance ?? (_instance = new OrderedDictionary()); }
}

 public static Mea Add(Double pre, Double rec)
{
     lock (Instance)
     {
        ...
     }
}

Mike Strobel の回答に基づいて、次の変更を行いました。

public static class Meas
{
    private static readonly OrderedDictionary Instance = new OrderedDictionary();
    private static readonly Object SyncLock = new Object();


    public static Mea Add(Double pre, Double rec)
    {
        lock (SyncLock)
        {
            Instance.Add(pre, rec);
            ...
        }
    }
}
4

3 に答える 3

9

Mike Strobel のアドバイスは良いアドバイスです。総括する:

  • ロックすることを特に意図したオブジェクトのみをロックします。
  • これらのロック オブジェクトは、宣言で初期化されるプライベートな読み取り専用フィールドである必要があります。
  • 独自のスレッドセーフな遅延初期化をロールしようとしないでください。Lazy<T>タイプを使用します。彼らが何をしているかを知っている専門家によって設計されました。
  • 保護された変数へのすべてのアクセスをロックします。
  • 次の 2 つの条件の両方が当てはまる場合、これらの適切なガイドラインに違反してください: (1) 顧客に影響を与えるパフォーマンスの問題が経験的に実証されており、より複雑なローロック スレッド セーフティ システムを使用することが問題に対する唯一の合理的な解決策であるという確固たる証拠があります。 、および (2) あなたは、プロセッサの最適化がローロック コードに与える影響についての第一人者です。たとえば、Grant Morrison または Joe Duffy の場合です。
于 2013-10-28T22:19:14.167 に答える
5

2 つのコードは同等ではありません。前者は、すべてのスレッドが常に同じロック オブジェクトを使用することを保証します。後者は遅延初期化されたオブジェクトをロックし、辞書の複数のインスタンス化を妨げるものは何もないため_instance、内容が失われます。

ロックの目的は何ですか?ディクショナリの単一初期化を保証する以外の目的を果たしますか? 2 番目の例でこれを達成できないことを無視して、それが唯一の目的である場合は、単純にLazy<T>クラスまたはダブルチェック ロック パターンを使用することを検討してください。

ただし、これは静的メンバーであるため (また、外部のジェネリック パラメーターをキャプチャするようには見えません)、おそらく AppDomain ごとに 1 回だけインスタンス化されます。readonlyその場合は、宣言でマークして初期化するだけです。おそらく、この方法ではあまり節約できません。

ベスト プラクティスに関心があるため、変更可能な値に対して構造体を使用しないでください。lockこれは、ローカル フィールドだけでなく、静的フィールドとインスタンス フィールドの両方にも当てはまります。揮発性フィールドをロックすることは特に悪い習慣です。そのキーワードの存在は、基になる値が変更されることを期待していることを示しているためです。フィールドをロックする場合は、ほとんどの場合フィールドである必要があります。メソッドの結果をロックすることも悪い習慣と見なされます。プロパティは事実上、特別に名前が付けられたアクセサー メソッドのペアであるため、これはプロパティにも当てはまります。readonly

于 2013-10-28T21:57:35.207 に答える
3

を他のクラスに公開しない場合はInstance、2 番目の方法で問題ありません (ただし、同等ではありません)。ロック オブジェクトをロック オブジェクトとして使用しているクラスに対して、ロック オブジェクトを非公開にしておくことをお勧めします。他のクラスもこのオブジェクトをロック オブジェクトとして使用できる場合にのみ、問題が発生する可能性があります。

(完全を期すため、および@Scott Chamberlainのコメントに関して:)これは、のクラスがInstance使用していないことを前提としてlock (this)います。

それにもかかわらず、プロパティは問題を引き起こす可能性があります。null 合体演算子は、null チェック + 割り当てにコンパイルされます... したがって、競合状態が発生する可能性があります。これについてもっと読みたいと思うかもしれません。ただし、可能であれば、遅延初期化をまったく削除することも検討してください。

于 2013-10-28T21:50:01.817 に答える