前段时间碰到一道面试题如下: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。
但是我测试的时候,快速连续打开这个页面时并没有出现这种情况,而是打开的页面显示的时间是相同的。有高手能解释下原因吗?

解决方案 »

  1.   

    代码段并不是竞争资源。我的理解是:多个线程共享代码段,但是每个线程有自己的IP和堆栈,但是对于代码段是只读的。因此每个线程执行代码的时候并不能影响其他线程的执行(除非使用同步机制)Thread.Sleep(1000 * 20); 只是当前执行此代码的县城sleep并不是所有线程都sleep。另外一个线索就是,线程切换可以发生在任何 时候。因此也说明其他线程不会等待这个Thread.Sleep(1000 * 20);执行完。
      

  2.   


    第一个页面显示的时间的确是20S前的时间,但是奇怪的是:连续快速打开的页面显示的时间是完全一样的。而如果GetDate()静态方法中去掉 Thread.Sleep(1000 * 20) 这句时,再测试的时候每个页面显示的时间是不一样的。
      

  3.   


    我们可以这样理解:打开的不同的页面相当于aspx页面所对应类的不同的实例,而GetDate()方法是静态方法,aspx页面的不同实例应该是调用同样的方法入口。
    Thread.Sleep(int i )是不是指当前的线程挂起i毫秒?那么的aspx不同实例是共用一个线程还是不同的线程?为什么会显示同样的时间呢?
      

  4.   

    连续快速打开的页面显示的时间是完全一样的这个时间应该是最后一次访问的时间,为什么呢因为test类中的静态变量是全类共享的.而不是实例对像
      public static string GetDate() 
        { 
            Response.Write(DateTime.Now.ToString());
            dt = DateTime.Now.ToString(); 
            
            Thread.Sleep(1000 * 20); 
            return  dt; 
        } 
    这样会在页面上输出二个时间,一定不一致
      

  5.   

    to zyug:
    是这样的,dt是全局变量,而第三次打开页面的时候可能前面2次还并没有完成GetDate()方法。刚才重新测试了,发现虽然Thread.Sleep(1000*20)但是每个页面显示的时间间隔并不是20S,而是几秒且每次间隔的时间不一样,也就是说aspx对应类的不同实例所使用的并不是同一个线程,有可能这几个线程是同步执行的,而不是顺序执行?
      

  6.   

    static方法并不是线程同步的楼主面向对象概念不清楚
      

  7.   

    static是面向对象的概念, 和线程无关lock是线程同步锁
      

  8.   

    明白lz的意思了。连续打开页面的状况应该是这样的。一个页面上显示的时间应该是执行到return之前的最后一次请求的时间。可以解释一下为什么会出现这样的现象:
    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能不能理解。
      

  9.   


    “访问量更大的时候 可能得到的间隔的时间越小”这个怎么解释?为什么时间间隔越小呢?还有asp.net默认的执行方式是不是单线程的呀?
      

  10.   

    asp.net 程序本身就是多线程的
      

  11.   

    to aimeast:
    非常感谢你这么仔细的回复,这个问题我明白了。现在的主要问题是:连续多次打开这个页面的时候,显示的时间间隔并不是线程sleep里面的20s。我的测试结果是每次间隔只有几秒,而且每次的间隔并不相等。是不是多次打开的页面是在不同的线程里处理的,这些线程之间并没有任何关系,并不是顺序执行的?我现在感觉那个面试官自己也没搞清楚怎么回事,我问他几个问题后,他就直接说我不适合他们的职位了:)
      

  12.   

    实质上每一个PAGE都不是单线程执行!只要是不同的请求!不过如果这个有上限那我就没考虑了,现在突然想到 事实上线程数应该是有上限吧···· 到那时候···不过 我觉得让所有的县城同时SLEEP不可能出现吧!!而且访问越多线程越多概率越小吧!倒是不一定返回的时间差越小····
      

  13.   

    对 并不是顺序执行 是CPU调度的 不可预测顺序的!
      

  14.   

    每个请求各自会等待20秒,但是无论请求并发数多少,这些等待都是独立进行的。这是因为每一个请求都是独立一个线程的,Thread.Sleep()是让当前线程等待,对每一个请求来说“当前线程”都是独立的。
      

  15.   

    .net编程中的线程机制大家可以详细解释下么:比如:asp.net默认是以多线程方式执行的?
    winForm编程时就是默认单线程编程的?如果默认就是多线程执行的,那么在.net环境下变成程序员自己实现多线程编程有什么意义呢?记得以前听一位前辈说过:VB编写的程序就是单线程方式执行的。
      

  16.   


    asp.net的多线程只是说多个请求的时候是多线程执行。但是就一个请求而言,还是单线程执行的。除非你在这个请求里使用了多线程。
      

  17.   

    to aimeast: 
    我测试的时候已经修改过GetDate()方法了,没有再使用静态变量。不知道IIS或者asp.net对多个请求的时候多线程执行是怎样实现的?有没有线程池等概念?
      

  18.   

    Test类如果修改成: 
    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; 
            }
        } 
    } 这样的话,就会出现死锁的情况吧?
      

  19.   


    会有不同的答案。“古老”的asp.net版本,并不是多线程地处理客户端请求的,另外也可能受到IIS版本(例如版本5、6)的限制,所以客户端请求实际上是排队的。而当你使用高版本的asp.net,以及高版本的IIS,性能会提高许多被,因为有更好更安全的并行处理模式。
      

  20.   

    例如你使用asp.net 1.1与asp.net 2.0对比就可以看出这个差别。
      

  21.   

    和asp.net版本应该没关系, 
    之所以学习asp.net之前不需要学习线程, 是因为asp.net帮你处理掉了客户端以及线程管理, 线程管理不需要你关心要不然学习asp.net之前先要学习线程了是考官自己不怎么懂, 又喜好追求技术, 喜好看技术文章又不看全面不看尽其意, 后来经过一知半解的理解后来就形成这种错误了。