此代码在 ASP.NET MVC 4 中线程安全吗?

问题描述 投票:0回答:3

根据我目前的理解,我认为这段代码不是线程安全的,但想确认一下。换句话说,我认为,尽管极不可能,代表不同 HTTP 请求的多个线程可能会混淆

_userName
属性的值。

public class SomeClass
{
    private static string _userName;

    public static string UserName
    {
        get
        {
            if (string.IsNullOrEmpty(_userName))
            {
                _userName = HttpContext.Current.User.Identity.Name;
            }

            return _userName; 
        }
    }
}

它是线程安全的吗?如果不是,则删除空检查,并始终直接访问

HttpContext.Current.User.Identity.Name
(在静态属性中)是线程安全的吗?

public class SomeClass
{
    public static string UserName
    {
        get
        {
            return HttpContext.Current.User.Identity.Name; 
        }
    }
}
c# asp.net asp.net-mvc multithreading thread-safety
3个回答
3
投票

你的两个例子非常不同。你是对的,你的第一个例子不是线程安全的,但更重要的问题是它不是会话安全的。访问

UserName
的第一个会话将设置用户名,并且 所有其他会话将使用相同的名称
UserName
在应用程序池被回收之前不会改变。如果第二个会话在第一个会话之后不久发出请求,那么从技术上来说第二个会话设置用户名是否重要?

如果您想缓存每个会话的用户名,请使用

Session
属性:

Session["UserName"] = HttpContext.Current.User.Identity.Name;

第二个块线程安全的,但它每次调用时都会返回当前用户名。因此,不必担心数据跨线程交叉,更不用说会话了。


2
投票
您的第二个解决方案效果很好。第一个是

根本不是线程安全的。在静态变量中缓存一个值会将其公开给所有线程,如果您有两个或多个同时请求,它们很可能会读取其他请求的值。你认为这极不可能,嗯...事实并非如此,恰恰相反。

此外,如果你确实希望一个值在多个线程之间共享,你应该使用一些同步机制来确保正确性。在第一个示例中,您访问

_userName

 3 次(2 次读取和 1 次写入)。您可能会遇到该变量最终得到不同值的情况,因此您应该将所有内容都包含在 
lock
 中。仅当您明确希望在线程之间共享此信息时才有效。

第二种方法有效,因为

HttpContext.Current

 的值是从当前 
执行上下文 检索的(因此它依赖于当前线程)。

还有一件事:在 ASP.NET 应用程序中,由于

线程敏捷性,您不应该依赖线程本地存储,因此如果您需要缓存值,请使用 HttpContext

 代替。您有一个 
Items
 属性,可让您仅在当前请求的持续时间内存储值。但在您的特定示例中,您不必缓存该值,因为它已经从 HTTP 上下文中检索。


0
投票
2

您的第二个解决方案效果很好。第一个根本不是线程安全的。在静态变量中缓存一个值会将其公开给所有线程,如果您有两个或多个同时请求,它们很可能会读取其他请求的值。你认为这极不可能,嗯...事实并非如此,恰恰相反。

© www.soinside.com 2019 - 2024. All rights reserved.