简体   繁体   中英

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.

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?

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 will not change until the App pool is recycled. 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["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). You can get into a situation where this variable ends up different values, so you should enclose everything in a 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).

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. You have an Items property which lets you store values for the duration of the current request only. but in your particular example, you don't have to cache this value, because it's already retrieved from the HTTP context.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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