我正在单个请求中的不同线程中从会话中读取/写入对象,如下所示:
public class HomeController : Controller
{
public int Index()
{
Task.WaitAll(DoStuff(), DoMoreStuff());
var foo = Session["foo"] as Foo;
return foo.MyProperty;
}
public Task DoStuff()
{
return Task.Factory.StartNew(() =>
{
var foo = Session["foo"] as Foo;
if (foo == null || foo.MyProperty == 1)
foo = new Foo { MyProperty = 1 };
Session["foo"] = foo;
});
}
public Task DoMoreStuff()
{
return Task.Factory.StartNew(() =>
{
var foo = Session["foo"] as Foo;
if (foo == null || foo.MyProperty == 1)
foo = new Foo { MyProperty = 2 };
Session["foo"] = foo;
});
}
}
public class Foo
{
public int MyProperty { get; set; }
}
现在这段代码中的逻辑显然没有意义,但是我提供它来显示我正在做的操作:
我没有修改现有的对象。这个代码一般可以破坏会话状态或内存吗?
这是具有默认进程内会话实现的ASP.NET MVC应用程序。
如果此代码可以破坏会话状态,我应该在每次访问此代码中的会话时锁定Session.SyncRoot
吗?
答案 0 :(得分:1)
读取和写入引用是原子的,但在这种情况下没有用,因为HttpSessionState
类不是线程安全的。
如果一个线程在会话状态中设置了一个项目,而另一个线程同时获取或设置了一个项目,则HttpSessionState
实例可能会被破坏。这会使它表现不正常或导致崩溃。
所以,是的,如果你想对来自不同线程的会话状态做任何事情,那么所有访问都需要在使用SyncRoot
属性锁定的代码块中(或者如果你愿意,可以使用你自己的对象)这一点)。
HttpSessionState
class的文档包含此标准声明:
"此类型的任何公共静态(在Visual Basic中为Shared)成员都是 线程安全。任何实例成员都不能保证是线程 。安全"
这意味着静态成员是线程安全的,因为他们没有做任何事情来专门破坏线程安全性,并且实例成员没有做任何事情来确保线程安全。它的设计根本不是线程安全的。