2

次のようなコードがあります。

public class UserCache
{
    private Dictionary<int, User> _users = new Dictionary<int, User>();

    public User GetUser(int id)
    {
        User u = null;

        lock (_users)
        {
            if (_users.containsKey(id))
                return _users[id];
        }

        //The below line is threadsafe, so no worries on that.
        u = RetrieveUser(id); // Method to retrieve from database;

        lock (_users)
        {
            _users.Add(id, u);
        }

        return u;
    }
}

辞書へのアクセスをロックしていますが、私のチームの誰かが、まだスレッドセーフではないと言っていました (説明なし)。質問は-これはスレッドセーフだと思いますか?

編集:解決策がどのようになるかを尋ねるのを忘れました。ユーザーの取得は時間のかかる操作であるため、メソッド全体をロックするつもりはないことに注意してください。

4

4 に答える 4

9

いいえ、スレッドセーフではありません。以前は存在しなかった同じ ID で同時に 2 回呼び出されたとします。

両方のスレッドが まで到達しRetrieveUser両方ともを呼び出します_users.Add(id, u)。キーが辞書に既に存在するため、2 番目の呼び出しは失敗します。

(余談ですが、読みやすくするために、ロック、if ステートメントなどに中括弧を使用することを強くお勧めします。)

于 2013-09-24T22:00:16.600 に答える
2

データ構造を破壊しないという意味でスレッドセーフです。メソッド全体がアトミックに動作するという意味で、スレッドセーフではありません。2 つのスレッドがアイテムの欠落を検出し、それを作成して追加する場合があります。加算器の 1 つが失敗します。

于 2013-09-24T22:00:42.407 に答える
-3

本当にスレッド セーフなコードを作成するには、シングルトン パターンを適用する必要があると思います。この時点で、クラスのインスタンスを 2 つ持つことができます。

于 2013-09-24T22:03:15.483 に答える