简体   繁体   English

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

[英]Is this code thread safe in ASP.NET MVC 4?

Based on my current understanding I do not think this code is thread safe but want to confirm. 根据我目前的理解,我认为此代码不是线程安全的,但需要确认。 In other words I think that, although it would be extremely unlikely, multiple threads representing different HTTP requests could potentially mix up the value of the _userName property. 换句话说,我认为,尽管这不太可能发生,但是代表不同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; 
        }
    }
}

Is it thread-safe and if not would removing the null check, and always accessing HttpContext.Current.User.Identity.Name directly (in a static property) be thread-safe? 它是线程安全的吗?如果不删除线程,则始终删除NULL检查并始终直接访问HttpContext.Current.User.Identity.Name是静态线程安全的吗?

public class SomeClass
{
    public static string UserName
    {
        get
        {
            return HttpContext.Current.User.Identity.Name; 
        }
    }
}

Your two examples are very different . 您的两个示例截然不同 You are right in that your first example is not thread safe, but the more important problem is that it's not session-safe . 您的第一个示例不是线程安全的,这是正确的,但是更重要的问题是, 它不是会话安全的 The first session that accesses UserName will set the username, and all other sessions will use that same name ! 访问UserName的第一个会话将设置用户名, 所有其他会话将使用相同的名称 UserName will not change until the App pool is recycled. 在回收应用程序池之前, UserName不会更改。 Does it matter that technically the second session set the user name if it made the request just slightly after the first? 技术上讲 ,如果第二个会话在第一个会话之后不久才发出请求,则设置用户名是否重要?

If you want to cache the user name for each session then use the Session property: 如果要缓存每个会话的用户名,请使用Session属性:

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

The second block is thread-safe, but it returns the current user name every time it's called . 第二个块线程安全的,但是每次调用都会返回当前用户名。 So there's no worry about data getting crossed across threads, let alone sessions. 因此,无需担心跨线程交叉数据,更不用说会话了。

Your second solution would work fine. 您的第二个解决方案将正常工作。 The first one is not thread safe at all . 第一个根本不是线程安全的 Caching a value in a static variable exposes it to all threads, and if you have two or more simultaneous requests, it's highly likely they will read some other request's value. 在静态变量中缓存值会将其公开给所有线程,并且如果您有两个或多个同时请求,则它们很可能会读取其他请求的值。 You think it's extremely unlikely , well... it's not, quite the opposite. 您认为这是极不可能的 ,嗯……事实并非完全相反。

Besides, if you really want a value to be shared across multiple threads, you should use some synchronization mechanism to ensure correctness. 此外,如果您确实希望在多个线程之间共享一个值,则应使用某种同步机制来确保正确性。 In your first example, you access _userName 3 times (2 reads and 1 write). 在第一个示例中,您访问_userName 3次(2次读取和1次写入)。 You can get into a situation where this variable ends up different values, so you should enclose everything in a lock . 您可能会遇到此变量最终具有不同值的情况,因此应将所有内容都放在lock And that's only when you explicitly want to share this information between threads. 仅当您明确希望在线程之间共享此信息时。

The second approach works because the value of HttpContext.Current is retrieved from the current execution context (so it's dependent on the current thread). 第二种方法之所以有效,是因为HttpContext.Current的值是从当前执行上下文中检索的(因此它取决于当前线程)。

Oh one more thing: in an ASP.NET application you shouldn't rely on thread-local storage because of thread agility , so if you need to cache values use the HttpContext instead. 另一件事:在ASP.NET应用程序中,由于线程敏捷性 ,您不应该依赖线程本地存储,因此,如果需要缓存值,请改用HttpContext You have an Items property which lets you store values for the duration of the current request only. 您有一个Items属性,该属性可让您仅在当前请求的持续时间内存储值。 but in your particular example, you don't have to cache this value, because it's already retrieved from the HTTP context. 但在您的特定示例中,您不必缓存该值,因为已经从HTTP上下文中检索了该值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM