日期:2014-05-18  浏览次数:20427 次

asp.net静态变量的问题
我用两台电脑做一个静态变量的测试
public class StaticTest{
 public static int tickcount=0;
 private static SqlConnection conn; 

 public AddTick(){
  tickcount++;
 }

 public void GetTick(){
  HttpContext.Current.Response.write(tickcount);
 }

 public static void OpenConnection(){ 
 if(conn == null){ 
  conn = new SqlConnection(connstr); 
  conn.Open(); 
  } 
  else{ 
  if(conn.State == ConnectionState.Closed){ 
  conn.Open(); 
  } 



两台电脑访问同一个页面,这个页面只调用 StaticTest.AddTick()和GetTick(),发现显示的数字是共享的,比如电脑A访问后tickcount=1,电脑B再访问tickcount=2,以此类推,说明静态变量确实是全局的,我个人觉得跟Application一样,现在问题就是
如果我先现在将一个SqlConnection作为静态变量的话,那它是不是也是全局共享的?如果我开连接的话,是不是只开一个就行了,
第一个用户开了后,其它用户就可以用这个开了的连接访问数据库,我觉得数据库的连接是web服务器和数据库之间的,用户访问的只是web服务器,我自己也知道连接都是用完就关,也知道IIS的连接池中会将经常访问的连接放到连接池中,即使conn.Close()连接也不会真的关闭,可我就是想不通SqlConnection作为静态变量时,连接到底会怎么运行?请各位大侠们指定迷津!!


------解决方案--------------------
个人理解:
劝搂主不要这么做
当应用程序启动的时候,clr会去了解这个类的内部结构,同时创建一个类型对象。类型对象内部包括了该类的对象指针,同步索引块以及静态字段等。
当你new这个类创建对象的时候就会创建一个实例对象,实例对象也包含了类型对象指针,无论创造了对少实例对象,它们的类型对象指针都指向类型对象。
实例对象只维护它自己的状态数据(也就是非静态数据),而类型对象则维护了静态数据,也就是说静态数据是所有该类实例共享的,因此就会产生所谓的线程安全问题。单件模式也就是利用了静态共享的原理来实现的。
------解决方案--------------------
假设你能够考虑到锁的逻辑必要性:

首先,你绝对不能平白无故去锁对象。程序运行中有许多线程需要“瞬间”访问数据库,相当于10个人都有权利自己决定何时喝水以及一天喝几次水,你偏偏人为规定所有人必须共用一个杯子,那么你的程序就可笑地效率低下。

其次,例如sqlDataReader是独占了sqlConnection,如果你多编几个程序就会碰到在主过程中打开sqlConnection然后在子过程中又要使用sqlDataReader的情况,此时同一个线程、同一个过程内部也“必须”使用多个sqlConnection。


如果你忽略了锁的逻辑必要性,那么可能根本不能上岗开发服务器软件,在个人机器上做出的服务器软件一拿上实际环境就会不断出现逻辑混乱的数据结果。