5

特にコレクションの単純なプロパティにアクセスするときにロックすることには、何か利点や害があります.Countか?(これは推奨されるか、推奨されないか、または少しでも問題ではありませんか?)(もちろん、書き込みまたは読み取りでロックする必要があります)

private Dictionary<string, bool> database = new Dictionary<string, bool>();
private object databaseLock = new object();
public int Count
{
    get
    {
        lock (databaseLock)
        {
            return database.Count;
        }
    }
}

個人的には、実際の理由ではなく、辞書へのアクセスをロックする必要があるという慣習を打ち破るのが賢明だと思います[*]。また、アクセスしているプロパティに関係なく、予想よりも多くの操作が行われる可能性もあります。

[*] C#の(ほとんどの)コレクションでCountは、はそれによって維持される整数であるため、常に不可分操作である必要があることを知っています

4

3 に答える 3

5

Dictionaryはい、ドキュメントはこれが安全であることを保証していないため、同時書き込みの場合はロックが必要です。その内部については何も推測できません。

この規則の例外には、極端な状況が必要です。

TL;DR: 文書化された行動だけに頼らないでください。

于 2012-12-07T21:30:18.157 に答える
2

この種のコードは、「危害」のカテゴリに大きく属します。同様に非常に深刻な種類の害。ロックは何も保護しません。プロパティ ゲッターがロックを終了してからナノ秒後に、スレッドがディクショナリに対して項目を追加または削除するのを止めるものは何もありません。これにより、Count 値がゴミ以外の何も返されなくなります。値を取得したときに、辞書に実際にいくつの項目があるかわかりません。このバグの最も有害な側面は、通常は正しいことです。

このコードは、スレッド競合を作成したことを保証します。これは、診断するのが断然最悪の種類のバグです。

于 2012-12-07T21:43:03.663 に答える
1

編集: usr が彼の答え で指摘しているように、Dictonary.Countスレッドセーフではありません。ドキュメントには次のように記載されています。

コレクションの列挙は、本質的にスレッドセーフな手順ではありません。列挙が書き込みアクセスと競合するまれなケースでは、列挙全体の間、コレクションをロックする必要があります。

つまり、同期必要です。コレクションを変更する可能性のある他のコードでも、同じロックを使用する必要があることに注意してください。Dictionary が複数のスレッドで使用されている場合は、 代わりにConcurrentDictionaryの使用を検討してください。

于 2012-12-07T21:31:09.360 に答える