3

Suppose I have singleton class that acts as a data cache. Multiple threads will read from the cache, and a single thread will periodically refresh it. It looks something like this:

public sealed class DataStore
{
    public static DataStore Instance { get { return _instance; } }
    public Dictionary<Foo, Bar> FooBar { get; private set; }

    static DataStore() { }
    private DataStore() { }

    public void Refresh() {
        FooBar = GetFooBarFromDB();
    }

    private static readonly DataStore _instance = new DataStore();
}

My question is essentially, is it safe to Refresh() while other threads may be accessing FooBar? Do I need to be using locks, or are my getting and setting operations atomic? Do I need to explicitly declare volatile fields to back up my properties?

P.S., If someone can think of a more descriptive title for this question, I would gladly welcome it.

Edit: Fixed my example to correct obviously non-atomic code.

4

4 に答える 4

8

はい、そのような場合は明示的な同期が必要ですFooBar。これは、書き込みが完了する前に別のスレッドが取得して読み取りを開始する可能性があるためです。

ただし、これを行うと、

public void Refresh() {
    var tmp = new Dictionary<Foo, Bar>();
    // Fill out FooBar from DB
    FooBar = tmp;
}

ある参照から別の参照への切り替えはアトミックであるため、明示的な同期を追加する必要はありません。

もちろん、Refreshメソッドの外側には書き込みがないという暗黙の前提があります。

編集:volatileまた、修飾子で宣言されたバッキング変数を使用して、自動実装されたプロパティから手動で実装されたプロパティに切り替える必要があります。

于 2012-07-31T00:54:18.990 に答える
2

あなたの例はスレッドセーフではありません。Dictionary はスレッドセーフなクラスではないため、Refresh の実行中に任意のスレッドが読み取りを行う可能性があります。を配置するか、lockのようなスレッドセーフなクラスのいずれかを使用できますConcurrentDictionary

于 2012-07-31T00:54:19.973 に答える
1

ディクショナリを公開しているため、ディクショナリ自体のメソッドへのアクセスに関して記述したコードでさらに問題が発生します。@Icarus が指摘したように、使用する必要ConcurrentDictionaryがありますが、インスタンスをロックする形式は役に立たないと主張します。

別のスレッドがコレクションを反復処理している間に、あるスレッドをコレクションに追加するのは簡単です。

編集私が言っていること..静的辞書またはその他のコレクションタイプを公開しないでください。常に並行バージョンを使用する

于 2012-07-31T01:04:27.633 に答える
1

さて、あなたの現在のコードがスレッドセーフではないことに同意します。FooBarしたがって、はクリティカル セクションであるため、同期機能を使用する必要があります。

放っておくと、クラス外の人がそれに応じて行動するpublicことを期待しています。DataStoreただし、これは不適切な設計上の決定です。

したがって、次のようにして、すべてを現在のクラスにラップすることをお勧めします。スレッドセーフな辞書を実装する最良の方法は何ですか?

于 2012-07-31T01:03:28.793 に答える