此代码线程在 ASP.NET MVC 4 中安全吗?
Is this code thread safe in ASP.NET MVC 4?
根据我目前的理解,我认为这段代码不是线程安全的,但想确认一下。换句话说,我认为,虽然这极不可能,但代表不同 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;
}
}
}
您的第二个解决方案可以正常工作。第一个 根本不是线程安全的 。在静态变量中缓存一个值会将其暴露给所有线程,如果您同时有两个或多个请求,它们很可能会读取其他请求的值。你觉得极不可能,嗯……不是,恰恰相反。
此外,如果你真的想要一个值被多个线程共享,你应该使用一些同步机制来确保正确性。在您的第一个示例中,您访问 _userName
3 次(2 次读取和 1 次写入)。您可能会遇到此变量最终具有不同值的情况,因此您应该将所有内容包含在 lock
中。只有当您明确希望在线程之间共享此信息时才会这样。
第二种方法有效,因为 HttpContext.Current
的值是从当前 execution context 中检索的(因此它取决于当前线程)。
还有一件事:在 ASP.NET 应用程序中,由于 thread agility,您不应该依赖线程本地存储,所以如果您需要缓存值,请使用 HttpContext
反而。您有一个 Items
属性 允许您仅在当前请求期间存储值。但在您的特定示例中,您不必缓存此值,因为它已经从 HTTP 上下文中检索到。
你的两个例子非常不同。你是对的,你的第一个例子不是线程安全的,但更重要的问题是它不是会话安全的。访问 UserName
的第一个会话将设置用户名,所有其他会话将使用相同的名称! UserName
在应用程序池被回收之前不会改变。 技术上 second 会话设置用户名是否重要,如果它在第一个请求之后发出请求?
如果要缓存每个会话的用户名,请使用 Session
属性:
Session["UserName"] = HttpContext.Current.User.Identity.Name;
第二个块是线程安全的,但它returns每次调用时都是当前用户名。所以不用担心数据跨线程,更不用说会话了。
根据我目前的理解,我认为这段代码不是线程安全的,但想确认一下。换句话说,我认为,虽然这极不可能,但代表不同 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;
}
}
}
您的第二个解决方案可以正常工作。第一个 根本不是线程安全的 。在静态变量中缓存一个值会将其暴露给所有线程,如果您同时有两个或多个请求,它们很可能会读取其他请求的值。你觉得极不可能,嗯……不是,恰恰相反。
此外,如果你真的想要一个值被多个线程共享,你应该使用一些同步机制来确保正确性。在您的第一个示例中,您访问 _userName
3 次(2 次读取和 1 次写入)。您可能会遇到此变量最终具有不同值的情况,因此您应该将所有内容包含在 lock
中。只有当您明确希望在线程之间共享此信息时才会这样。
第二种方法有效,因为 HttpContext.Current
的值是从当前 execution context 中检索的(因此它取决于当前线程)。
还有一件事:在 ASP.NET 应用程序中,由于 thread agility,您不应该依赖线程本地存储,所以如果您需要缓存值,请使用 HttpContext
反而。您有一个 Items
属性 允许您仅在当前请求期间存储值。但在您的特定示例中,您不必缓存此值,因为它已经从 HTTP 上下文中检索到。
你的两个例子非常不同。你是对的,你的第一个例子不是线程安全的,但更重要的问题是它不是会话安全的。访问 UserName
的第一个会话将设置用户名,所有其他会话将使用相同的名称! UserName
在应用程序池被回收之前不会改变。 技术上 second 会话设置用户名是否重要,如果它在第一个请求之后发出请求?
如果要缓存每个会话的用户名,请使用 Session
属性:
Session["UserName"] = HttpContext.Current.User.Identity.Name;
第二个块是线程安全的,但它returns每次调用时都是当前用户名。所以不用担心数据跨线程,更不用说会话了。