更新字典的静态方法在 ASP.NET 中 - 对字典本身进行 lock() 安全吗?

发布于 2024-10-09 02:15:17 字数 747 浏览 0 评论 0原文

我有一个类,它维护来自域控制器的缓存查找结果的静态字典 - 用户的名字和电子邮件。

我的代码看起来像:

private static Dictionary<string, string> emailCache = new Dictionary<string, string>();

protected string GetUserEmail(string accountName)
{
    if (emailCache.ContainsKey(accountName))
    {
        return(emailCache[accountName]);
    }

    lock(/* something */)
    {
        if (emailCache.ContainsKey(accountName))
        {
            return(emailCache[accountName]);
        }

        var email = GetEmailFromActiveDirectory(accountName);
        emailCache.Add(accountName, email);
        return(email);
    }
}

需要锁吗?我认为是这样,因为多个请求可能同时执行查找,并最终尝试将相同的键插入同一个静态字典中。

如果需要锁,我是否需要创建一个专用的静态对象实例来用作锁令牌,或者使用实际的字典实例作为锁令牌是否安全?

I have a class that maintains a static dictionary of cached lookup results from my domain controller - users' given names and e-mails.

My code looks something like:

private static Dictionary<string, string> emailCache = new Dictionary<string, string>();

protected string GetUserEmail(string accountName)
{
    if (emailCache.ContainsKey(accountName))
    {
        return(emailCache[accountName]);
    }

    lock(/* something */)
    {
        if (emailCache.ContainsKey(accountName))
        {
            return(emailCache[accountName]);
        }

        var email = GetEmailFromActiveDirectory(accountName);
        emailCache.Add(accountName, email);
        return(email);
    }
}

Is the lock required? I assume so since multiple requests could be performing lookups simultaneously and end up trying to insert the same key into the same static dictionary.

If the lock is required, do I need to create a dedicated static object instance to use as the lock token, or is it safe to use the actual dictionary instance as the lock token?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

峩卟喜欢 2024-10-16 02:15:44

据我所知,使用了额外的对象作为互斥体:

private static object mutex = new object();

protected string GetUserEmail(string accountName)
{
    lock (mutex)
    {
        // access the dictionary
    }
}

As far as I could see, additional object as a mutex was used:

private static object mutex = new object();

protected string GetUserEmail(string accountName)
{
    lock (mutex)
    {
        // access the dictionary
    }
}
遥远的她 2024-10-16 02:15:41

MSDN 文档指定,永远不要对可以在您自己的代码之外读取或修改的公共对象使用 lock() 语句。

我宁愿使用对象实例而不是您尝试修改的对象,特别是如果该字典具有允许外部代码访问它的访问器。

我在这里可能是错的,从一年前开始我就没有写过一行C#。

MSDN documentation specify that you should never use the lock() statement over a public object that can be read or modified outside your own code.

I would rather use an object instance rather than the object you attempt to modify, specifically if this dictionnary has accessors that allows external code to access it.

I might be wrong here, I didn't write a line of C# since one year ago.

謸气贵蔟 2024-10-16 02:15:39

确实需要锁。

通过使用锁,您可以确保一次只有一个线程可以访问临界区,因此不需要额外的静态对象。

您可以锁定字典对象本身,但我只需使用 object lock =new object(); 作为我的锁。

The lock is indeed required.

By using lock, you ensure that only one thread can access the critical section at one time, so an additional static object is not needed.

You can lock on the dictionary object itself, but I would simply use a object lock =new object(); as my lock.

无边思念无边月 2024-10-16 02:15:37

由于字典是私有的,因此您应该可以安全地锁定它。锁定的危险(据我所知)是您现在不考虑的其他代码也可能锁定对象并可能导致死锁。使用私人词典,这不是问题。

坦率地说,我认为您只需更改代码以不调用字典 Add 方法,而是使用属性设置语句即可消除锁定。那我根本不相信锁。

更新:以下是来自 Dictionary 上的私有 Insert 方法的代码块,该方法由 Item setter 和 Add 方法调用。请注意,当从项目设置器调用时,“add”变量设置为 false,当从 Add 方法调用时,“add”变量设置为 true:

if (add)
{
    ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
}

所以在我看来,如果您不担心覆盖字典中的值(在本例中不会出现),然后使用不锁定的属性设置器就足够了。

Since the dictionary is private, you should be safe to lock on it. The danger with locking (that I'm aware of) is that other code that you're not considering now could also lock on the object and potentially lead to a deadlock. With a private dictionary, this isn't an issue.

Frankly, I think you could eliminate the lock by just changing your code to not call the dictionary Add method, instead using the property set statement. Then I don't believe the lock at all.

UPDATE: The following is a block of code from the private Insert method on Dictionary, which is called by both the Item setter and the Add method. Note that when called from the item setter, the "add" variable is set to false and when called from the Add method, the "add" variable is set to true:

if (add)
{
    ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
}

So it seems to me that if you're not concerned about overwriting values in your dictionary (which you wouldn't be in this case) then using the property setter without locking should be sufficient.

一枫情书 2024-10-16 02:15:34

是的,只要其他线程上的代码可以/将访问静态对象,就需要锁。

是的,锁定字典本身是安全的,只要它不能通过公共 getter 访问即可。然后调用者可能会使用该对象来锁定自身,这可能会导致死锁。因此,如果您的字典有些公开,我建议使用单独的对象来锁定。

Yes, the lock is required as long as code on other threads can/will access the static object.

Yes, its safe to lock on the dictionary itself, as long as its not accessible via a public getter. Then the caller might use the object for locking itself and that might result in deadlocks. So i would recommend to use a separate object to lock in if your dictionary is somewhat public.

感情废物 2024-10-16 02:15:32

.NET 中的集合不是线程安全的,因此确实需要锁。使用字典的另一种方法是使用 .NET 4.0 中引入的并发字典

http:// /msdn.microsoft.com/en-us/library/dd287191.aspx

Collections in .NET are not thread safe so the lock is indeed required. An alternative to using the dictionary one could use Concurrent dictionaries introduced in .NET 4.0

http://msdn.microsoft.com/en-us/library/dd287191.aspx

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文