前段时间碰到一道面试题如下:test.aspx页面有如下代码:
Response.Write(Test.GetDate());Test类如下:
public class Test
{
static string dt="";
public static string GetDate()
{
dt = DateTime.Now.ToString(); Thread.Sleep(1000 * 20);
return dt;
}
}
问这种情况下可能会出现什么情况?面试时我问考官答案,他说在多用户同时访问页面时可能一直等待,因为静态方法的线程等待20s。
但是我测试的时候,快速连续打开这个页面时并没有出现这种情况,而是打开的页面显示的时间是相同的。有高手能解释下原因吗?
Response.Write(Test.GetDate());Test类如下:
public class Test
{
static string dt="";
public static string GetDate()
{
dt = DateTime.Now.ToString(); Thread.Sleep(1000 * 20);
return dt;
}
}
问这种情况下可能会出现什么情况?面试时我问考官答案,他说在多用户同时访问页面时可能一直等待,因为静态方法的线程等待20s。
但是我测试的时候,快速连续打开这个页面时并没有出现这种情况,而是打开的页面显示的时间是相同的。有高手能解释下原因吗?
第一个页面显示的时间的确是20S前的时间,但是奇怪的是:连续快速打开的页面显示的时间是完全一样的。而如果GetDate()静态方法中去掉 Thread.Sleep(1000 * 20) 这句时,再测试的时候每个页面显示的时间是不一样的。
我们可以这样理解:打开的不同的页面相当于aspx页面所对应类的不同的实例,而GetDate()方法是静态方法,aspx页面的不同实例应该是调用同样的方法入口。
Thread.Sleep(int i )是不是指当前的线程挂起i毫秒?那么的aspx不同实例是共用一个线程还是不同的线程?为什么会显示同样的时间呢?
public static string GetDate()
{
Response.Write(DateTime.Now.ToString());
dt = DateTime.Now.ToString();
Thread.Sleep(1000 * 20);
return dt;
}
这样会在页面上输出二个时间,一定不一致
是这样的,dt是全局变量,而第三次打开页面的时候可能前面2次还并没有完成GetDate()方法。刚才重新测试了,发现虽然Thread.Sleep(1000*20)但是每个页面显示的时间间隔并不是20S,而是几秒且每次间隔的时间不一样,也就是说aspx对应类的不同实例所使用的并不是同一个线程,有可能这几个线程是同步执行的,而不是顺序执行?
public class Test
{
static string dt = "";
public static string GetDate()
{
dt = DateTime.Now.ToString(); Thread.Sleep(1000 * 20);
return dt;
}
}dt是个静态变量,全局只有一个。在return之前,新的请求会把当前请求的dt给修改掉。
假设每秒钟都会对这个页面有一个请求,从第0秒开始计时,共21次请求
进行如下模拟:
第0秒把dt修改为0。
第1秒把dt修改为1。
第2秒把dt修改为2。
...
...
...
第18秒把dt修改为18。
第19秒把dt修改为19。同时第0秒的请求返回dt的值。这时候dt的值是19,而不是0。
第20秒把dt修改为20。同时第1秒的请求返回dt的值。这时候dt的值是20,而不是1。
第21秒没有修改dt。同时第2秒的请求返回dt的值。这时候dt的值是20,而不是2。
第22秒没有修改dt。同时第3秒的请求返回dt的值。这时候dt的值是20,而不是3。
...
...
如果不想出现此现象,那么要去掉static修饰符。
public class Test
{
string dt = "";
public string GetDate()
{
dt = DateTime.Now.ToString(); Thread.Sleep(1000 * 20);
return dt;
}
}Response.Write(new Test().GetDate()); 不知道lz能不能理解。
“访问量更大的时候 可能得到的间隔的时间越小”这个怎么解释?为什么时间间隔越小呢?还有asp.net默认的执行方式是不是单线程的呀?
非常感谢你这么仔细的回复,这个问题我明白了。现在的主要问题是:连续多次打开这个页面的时候,显示的时间间隔并不是线程sleep里面的20s。我的测试结果是每次间隔只有几秒,而且每次的间隔并不相等。是不是多次打开的页面是在不同的线程里处理的,这些线程之间并没有任何关系,并不是顺序执行的?我现在感觉那个面试官自己也没搞清楚怎么回事,我问他几个问题后,他就直接说我不适合他们的职位了:)
winForm编程时就是默认单线程编程的?如果默认就是多线程执行的,那么在.net环境下变成程序员自己实现多线程编程有什么意义呢?记得以前听一位前辈说过:VB编写的程序就是单线程方式执行的。
asp.net的多线程只是说多个请求的时候是多线程执行。但是就一个请求而言,还是单线程执行的。除非你在这个请求里使用了多线程。
我测试的时候已经修改过GetDate()方法了,没有再使用静态变量。不知道IIS或者asp.net对多个请求的时候多线程执行是怎样实现的?有没有线程池等概念?
public class Test
{
object tempObj=new object();
static string dt="";
public static string GetDate()
{
lock(tempObj)
{
dt = DateTime.Now.ToString(); Thread.Sleep(1000 * 20);
return dt;
}
}
} 这样的话,就会出现死锁的情况吧?
会有不同的答案。“古老”的asp.net版本,并不是多线程地处理客户端请求的,另外也可能受到IIS版本(例如版本5、6)的限制,所以客户端请求实际上是排队的。而当你使用高版本的asp.net,以及高版本的IIS,性能会提高许多被,因为有更好更安全的并行处理模式。
之所以学习asp.net之前不需要学习线程, 是因为asp.net帮你处理掉了客户端以及线程管理, 线程管理不需要你关心要不然学习asp.net之前先要学习线程了是考官自己不怎么懂, 又喜好追求技术, 喜好看技术文章又不看全面不看尽其意, 后来经过一知半解的理解后来就形成这种错误了。