C#积累(二)——ASP.NET的Session会加锁
项目:ASP.NET 网站程序
版本:.net 3.5
运行IDE:VS 2008 SP1
项目文件:Default.aspx
通过设置页面上的EnableSessionState可以为Session加锁:
EnableSessionState="True":页面对Session设置读写锁。有这个SessionID的Session在每个请求过程中会被锁定.
EnableSessionState="False":页面不需要访问Session。如果代码使用Session对象,就会抛出HttpException异常.
EnableSessionState="ReadOnly":页面对Session设置读取锁.读取锁和读锁之间不互斥,但是和读写锁互斥.
一个现象:
页面设置EnableSessionState="True"的时候Session会给每个请求加上读写锁,言下之意就是一旦一个请求访问了申请并在请求没有结束的时候会一直占有Session,其余请求访问Session的时候必须等待占有Session的请求结束。
但是经过我实验发现这个定义对第一次请求似乎不起作用,请看Default.aspx.cs:
{
if (Request.QueryString["test"] == null)
{
Session["test"] = "23";
Session["test"] = persist();
//Session["test"] = "over";
}
else
{
Session["test"] = "over";
}
Response.Write(Session["test"].ToString());
}
string persist()
{
System.Threading.Thread.Sleep(6553500);
return "over";
}
首先在浏览器输入:http://localhost/SessionExcise/Default.aspx由于Sleep会一直执行
在IE上Ctrl+T(保证和刚才是同一个Session)输入:http://localhost/SessionExcise/Default.aspx?test=2按道理来说会被阻塞,因为Session被刚才的请求加了读写锁被占有。但是结果没有被阻塞,执行成功浏览器上显示over。
现在改变执行顺序先执行http://localhost/SessionExcise/Default.aspx?test=2,不用说执行成功
再Ctrl+T输入http://localhost/SessionExcise/Default.aspx因为Sleep被阻塞
再Ctrl+T输入http://localhost/SessionExcise/Default.aspx?test=2结果这次符合了定义被阻塞了
为什么第一次输入http://localhost/SessionExcise/Default.aspx?test=2没有被阻塞呢?
原因就在SessionID上,第一次先输入http://localhost/SessionExcise/Default.aspx由于请求没有发送SessionID服务器认为是新会话会在响应中给浏览器分配SessionID,又由于Sleep的缘故,响应中分配的SessionID并不会返回给浏览器,由于浏览器没有分配到SessionID,Crtl+T后输入http://localhost/SessionExcise/Default.aspx?test=2请求仍然没有发送SessionID给服务器,所以服务器认为原先的http://localhost/SessionExcise/Default.aspx请求和现在的http://localhost/SessionExcise/Default.aspx?test=2都是新会话,都会为这两个请求单独分配SessionID,由于服务器认为两次请求是不同的会话所以自然不会产生会话阻塞
但是第二个执行顺序由于第一输入http://localhost/SessionExcise/Default.aspx?test=2响应返回后浏览器分配到了SessionID,之后再用Ctrl+T发出的请求都会沿用这个SessionID,所以接下来在http://localhost/SessionExcise/Default.aspx后再输入http://localhost/SessionExcise/Default.aspx?test=2被服务器判定为同一会话,会话中的读写锁就会起作用了造成阻塞,这点值得注意!