使用 Session 线程安全吗?

Posted

技术标签:

【中文标题】使用 Session 线程安全吗?【英文标题】:Is working with the Session thread-safe? 【发布时间】:2011-10-24 04:36:28 【问题描述】:

考虑一个用户同时发出多个请求,我是否必须锁定所有与 Session 一起工作的代码?

例如,如果我有以下场景,用户在浏览器的一个选项卡中打开一个页面,然后在第二个选项卡中退出。

请求 1:

if(Session["user"] != null)
    lblName.Text = Session["user"].Name;

请求 2:

if(logout)
   Session["user"] = null;

请求 1 在访问 Name 属性时是否可能引发 NullPointerException?我是否需要锁定请求 1 中的代码,以确保在检查 null 后用户仍然存在?还是 ASP.NET 会以某种方式自动处理这个问题?

【问题讨论】:

我会传递参考信息,对吧?如果 Request2 调用 Session["user"].Dispose() 会怎样?这会影响我在 Request1 中退出 Session 的用户吗? 是的,在这种情况下,您可以使用已处置的对象。 Peter Ruderman 的回答说它在请求 1 中不能为空。两种意见 - 什么是正确的? @atticae:这取决于您使用的是内存还是基于 SQL 的会话状态。在任何情况下,您都应该假设该对象可以在多个线程之间共享并适当地同步访问。 @Darryl Braaten:请求 1 中没有竞争条件,因为 ASP.NET 在 Session 上使用读取器和写入器锁。请阅读msdn.microsoft.com/en-us/library/aa479041.aspx 【参考方案1】:

与往常一样,答案取决于您所说的“安全”是什么意思。在 ASP .NET 中,每个请求都获得对其会话状态的独占访问权。这意味着您不必担心在单个请求的范围内同步访问。如果 Session["user"] 不为空,则在当前请求的整个持续时间内它将为非空。在您的示例中,请求 1 永远不会引发空引用异常。

【讨论】:

谢谢,这正是我想知道的。不过,这与 Darryl Braaten 在上面的 cmets 中所写的内容相矛盾。那么谁是对的呢? :) 这并不完全正确——在默认的 InProc 模式下,ASP.NET 不会复制会话状态;它使用读取器和写入器锁来防止不可重复读取。这意味着请求 2 将阻塞直到请求 1 完成,因为请求 1 持有此会话的读取器锁定。效果是一样的,但是机制却大不相同。 是的,图片比我上面描述的要复杂一些,但关键是你不必同步访问。根据请求是否被标记为需要会话状态,您将获得独占访问或独占副本。【参考方案2】:

对同一会话的 ASP.NET 应用程序的两个请求,其中处理程序不使用 IReadOnlySessionState 标记接口或为您的页面打开 EnableSessionState="ReadOnly",将由 ASP.NET 运行时序列化以保证状态的一致性。因此,如果您有两个能够写入会话状态的页面,那么无论客户端在他们这边做什么,它们都将被串行访问。

页面/处理程序是否要写入会话状态取决于您的应用程序代码使用上述技术向 ASP.NET 发出信号。否则,所有请求都将被序列化,并且您的 Web 应用程序的性能将受到影响。

【讨论】:

好吧,我从没想过 Session 是一个如此复杂的话题。我在这里学到了很多东西,谢谢大家。 在 ASP.Net Core 中也是如此吗?我看到了 DistributedSession 实现(默认情况下正在实例化)并且没有任何序列化技术的痕迹,比如锁...... @g.pickardou Asp.net 上的这种威胁安全是否仍然适用于 ASP.NET Core。 ?我在从同一浏览器上的不同并发请求读取和写回会话上的同一键时遇到并发问题【参考方案3】:

在 ASP.NET 中,Session module uses a pair of reader/writer locks per session,因此请求 1 将具有一致的读取,而请求 2 将阻塞直到请求 1 完成。

【讨论】:

【参考方案4】:

是的,Session 是线程安全的。

没有必要锁定任何东西。但是,检查这些值的需求永远不会停止。

更新

检查@Peter Ruderman 的回答 :)

我不会复制它的体面:)

【讨论】:

我猜我的问题标题是错误的,应该是“正在使用会话线程安全” 你应该更新你的问题,因为这会改变答案。 好的,现在做。我仍然不认为标题是完美的,但比以前更好。 ;) 那我们需要检查什么?

以上是关于使用 Session 线程安全吗?的主要内容,如果未能解决你的问题,请参考以下文章

mongodatabase mongocollection 线程安全吗

Hibernate中的session的线程安全问题

hibernate中session线程安全的实现

Python 的 Requests 库线程中的 Session 对象是不是安全?

HIbernate Session 线程安全的问题

Java+线程内部调用实例方法会多线程安全吗?