为什么这段代码不是线程安全的?

Mik*_*ike 2 c# multithreading thread-safety thread-synchronization

我有一段这样的代码:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在锁定对字典的访问权限,但我团队中有人告诉它仍然没有线程安全(没有解释).问题是 - 你认为这是线程安全的吗?

编辑:忘了询问,解决方案是什么样的.请注意我不想锁定整个方法,因为检索用户是一个耗时的操作.

Jon*_*eet 9

不,它不是线程安全的.想象一下,它使用相同的ID同时调用两次,这在以前不存在.

这两个线程会走这么远的RetrieveUser,他们倒是调用_users.Add(id, u).第二次调用将失败,因为密钥已经存在于字典中.

(顺便说一句,为了便于阅读,我强烈建议使用大括号来锁定if语句等.)

  • @ I4V抛出一个只能在多线程代码中发生的异常可能被称为"非线程安全".如果代码使用`_users [id] = u`,另一方面我同意. (2认同)