随笔-65  评论-1102  文章-2  trackbacks-35

数据成员可以分静态变量非静态变量两种.
 静态成员:静态类中的成员加入static修饰符,即是静态成员.可以直接使用类名+静态成员名访问此静态成员,因为静态成员存在于内存,非静态成员需要实例化才会分配内存,所以静态成员不能访问非静态的成员..因为静态成员存在于内存,所以非静态成员可以直接访问类中静态的成员.
 
 非成静态员:所有没有加Static的成员都是非静态成员,当类被实例化之后,可以通过实例化的类名进行访问..非静态成员的生存期决定于该类的生存期..而静态成员则不存在生存期的概念,因为静态成员始终驻留在内容中..
 
 一个类中也可以包含静态成员和非静态成员,类中也包括静态构造函数和非静态构造函数..
 
 对于winApp来说,静态成员对于程序员本身省了很多事,而且因为静态成员驻留内存,在方法与方法之间传递共享数据的时候,所以静态成员成了我的首选..但是不要因为方便,大量使用,尤其是在内存紧张或者
 用静态方法操作一些共享值的时候.或者要写多用户系统的时候,要慎之又慎.比如:
 static int id = 0;
 sql = "select * from table where id=" + id;

 
 如果这样写的话,在单机测试的时候没有问题,但是在多人同时对数据进行测试的时候,就会有问题了.假如,A用户访问他的id是20,则id的值在内存中为20,而此时B用户访问,他的id是30,则id在内存中的值是30..A用户的id值则被更改了..如果此时你将这个方法用非静态成员来写,则不会出现这样的情况..因为非静态成员是你声明的时候,实例化的时候才会分配内存..所以A用户访问的时候,App会因为A实例化而给A用户的请求分配内存..而B用户访问的时候也一样会因为B用户的访问而分配内存..所以两个用户访问的是不同的内存块..所以不会出现数据覆盖和错乱的现象...
 
我想这样的情况应该能很好的说明静态变量和非静态成员的区别..
  
相对于webApp而言,在winApp下使用static的时候要比webApp下考虑的因素要少的多,因为webApp本来就是一个多用户的系统,所以使用static的时候更应该小心..

而我对static在webApp下的使用存在一个疑问,如果一个静态方法,例如:

static string aa(string str){
 //经过一系列操作..
 return str;
}

或者返回一个DataSet的静态方法
static DataSet aa(string str){
 //经过一系列操作..
 return DataSet;
}

这个时候,在访问量大的时候,程序出现了并发,会不会发生错乱??我以前的项目使用的公用函数类中使用了大量的静态方法,不过好在访问量不大,一直没有问题..在发这个文章之前,我查找了MSDN,CSDN,搜索了一些关于静态成员的文章,但是都没有一个明确的说明..虽然,自己在项目中也测试了这么长时间也没有问题..但是总觉得有这个可能发生..

不知道大家是否在项目中碰到类似的疑惑呢??请有过这方面经验的朋友指教..

posted on 2005-08-31 18:08 难得一蠢 阅读(6606) 评论(38)  编辑 收藏 所属分类: C#.NET

评论:
#1楼  2005-08-31 18:39 | 海蓝心      
有同感
这种发生的机会是存在的

  回复  引用  查看    
#2楼  2005-08-31 18:48 | idior      
---
在发这个文章之前,我查找了MSDN,CSDN,搜索了一些关于静态成员的文章,但是都没有一个明确的说明.
---
你知道为什么没有说明吗?
你走的根本就是错路。
滥用静态方法是结构化编程的典型表现!去学学什么叫面向对象。

  回复  引用  查看    
#3楼  2005-08-31 19:37 | 風語者·疾風      
要测试其实很简单的嘛
写个程序,然后开一个用户去进断点;然后再连一个用户去调用,然后让后者先通过断点,这个时候你就会发现你的数据已经被咔嚓~~~~~~~

同意楼上的说法。
  回复  引用  查看    
#4楼  2005-08-31 20:20 | 补丁      
我怎么觉得仅仅是静态方法的话应该没有问题
如果会有影响
岂不是说静态方法不能进行递归调用???呵呵

同时调用静态方法和同时调用某个对象的某个方法有很大区别么?
只要不涉及全局变量
应该没有并发问题...
  回复  引用  查看    
#5楼  2005-08-31 21:17 | FantasySoft      
注意静态成员变量跟静态方法的区别。
  回复  引用  查看    
#6楼  2005-09-01 01:24 | bighippo [未注册用户]
恩恩!
静态方法.....你提到的是静态方法..你提到的是个方法..
  回复  引用    
#7楼 [楼主] 2005-09-01 07:33 | 难得一蠢      
To:idior
你走的根本就是错路,滥用静态方法是结构化编程的典型表现!去学学什么叫面向对象
====================================

怎么是错路了??你怎么知道我是滥用了???我又说过我滥用吗??不要以为就只有你一个人明白什么是面相对象...

我只是讨论一下对于一些公用的函数使用静态调用会不会出现问题而已...并不是说我喜欢滥用静态方法..,你可以换个角度,如果你觉得每次使用公用函数,都new一个出来很过瘾..那就不要讨论了...
  回复  引用  查看    
#8楼  2005-09-01 08:02 | feelwindy      
任何东西都有一个度,再好的东西滥了也不就变成坏东西了,
但这个滥的度是怎么样的呢?又有谁知道?只能应实际情况而具体变化了.

我们在做项目时,对于一些基本的处理方法,都采用静态方法.
什么是处理方法呢?就是用来处理一些数据的,数据都是由外部传入,它只是做为一个加工站在这里使用.
而对于静态变量,这个东西的确有点恐怖,所以我们平时很少用,

我们以前做的项目,几万人并发,也没问题,东西是好的,就是要看你怎么用,还是把注意力多放点在架构与设计上吧
  回复  引用  查看    
#9楼 [楼主] 2005-09-01 08:12 | 难得一蠢      
To:feelwindy

什么是处理方法呢?就是用来处理一些数据的,数据都是由外部传入,它只是做为一个加工站在这里使用.

=====================================

终于等到你了..呵呵..要的就是这句话..我主要讨论的问题就是在何时适当的使用static,而不是一味的滥用..就好像杀牛用牛刀,杀鸡用菜刀一样..这样才能达到目的..
感谢feelwindy
  回复  引用  查看    
#10楼  2005-09-01 09:10 | 守望红木[吴]      
方法而已,不会出现所谓的线程不安全啊。呵呵
如果这个方法里面读取了静态变量就要注意,静态变量本身无法保证线程安全!

还是说话都文雅一点的好!
至于idor说的”滥用静态方法是结构化编程的典型表现!去学学什么叫面向对象。“,这典型的学者说话一样,说的都对就是没用,啥好东西滥用那肯定不好的!
  回复  引用  查看    
#11楼  2005-09-01 09:12 | 81      
不说是否滥用,如果你出现冲突,说明你没有理解静态成员变量和静态方法的区别,静态方法本身只是一段代码,不管怎么调用他都不会出现问题。但静态成员变量就不行了,他被所有用户共享,如果一个用户改变了他,肯定会影响到别人,这就是常说的并发冲突问题,一般来说在修改共享成员变量时要lock!
  回复  引用  查看    
#12楼  2005-09-01 09:20 | rainlake [未注册用户]
不会冲突。除非你引用了别的静态变量或者全局变量或者数据库里的内容发生了变化,才会导致数据不一致
  回复  引用    
#13楼 [楼主] 2005-09-01 10:38 | 难得一蠢      
看了大家的意见和评论,总算是有点觉悟了..呵呵..

总结一下,公用的处理函数,使用静态方法应该没有问题..牵涉到数据共享,静态变量的函数要多考虑...静态变量要小心使用..

引用思归的一句话:一个东西的好处是在你需要用的时候才能体会到的..

不能什么事情都不能一棒子打死..一个对象存在必然有它存在的理由...

祝大家编程快乐..开工干活了...
  回复  引用  查看    
#14楼  2005-09-01 12:42 | albert_wang [未注册用户]
不錯,不錯,同樣也解決了我的疑惑,一直使用靜態方法,雖說一直沒問題,但也一直存在疑惑,現在霍然開朗了
  回复  引用    
#15楼  2005-09-01 13:34 | 妖居      
静态变量还是少用为好。
  回复  引用  查看    
#16楼  2005-09-01 13:57 | 小春 [未注册用户]
刚开始看我还吓了一跳,静态……

原来是静态变量。而不是静态方法会出种这种情况(因为我在类中经常使用静态方法。也会出现过什么问题,因为不喜欢经常NEW,静态变量从来不敢用)
  回复  引用    
#17楼  2005-09-01 14:07 | shootingstars [未注册用户]
只要当资源的访问可能发生冲突时才需要考虑互斥的问题。
这与这个方法是否静态没有关系,成员函数在访问共享资源的时候同样需要考虑互斥访问的问题。

--------------------------------

BS idior , 估计是当老师当习惯了。
  回复  引用    
#18楼  2005-09-02 08:33 | chon [未注册用户]
我想idior的担心也不是不对的,就像上面说的,只要不烂用就没关系了.
静态变量是一个公共的变量内存,有可能会冲突的.
如果是静态方法,那很多线程去调用就不会冲突了,因为方法只是程序代码而以,里面的临时变量是放在堆栈里面的,所以每次调用方法(无论静态还是动态)临时变量都是放在自己的堆栈里.

说到静态成员的使用在很多经典代码中也存在.
如人们常说的设计模式中的单件模式,工厂模式就有可能用到.

我想可以理解上可以把整个类看成是一个对象实例,而静态成员就是这个对象的动态成员.
  回复  引用    
#19楼 [楼主] 2005-09-03 07:41 | 难得一蠢      
to:chon
恩,说的对.我那个错误的静态方法就是引用了静态变量才早上了数据冲突..

静态方法的使用在C#中就有很多,适当使用可以避免多次new实例消耗内存.

itior可能是没看清楚主题..
  回复  引用  查看    
#20楼  2005-09-13 14:18 | 星仔      
我对静态变量有一次惨痛的教训,就像笔者写的例子,曾别经理猛K过
  回复  引用  查看    
#21楼  2005-10-10 08:49 | Paladin_wu [未注册用户]
曾经也有这样的疑惑,但看过PetShop3.0中SQLHelper类的写法,静态方法应该没有并发问题,否则微软拿它做范例岂不是很没面子。
  回复  引用    
#22楼  2005-10-19 17:22 | CCC [未注册用户]
我想MS在程序的内核里对静态字段应该有处理过的,使它只能被单一的实例访问!
如果真不是这样,那这个BUG可就大了,还.Net呢,不死才怪!
  回复  引用    
#23楼  2006-01-19 12:04 | A.Z [未注册用户]
为什么在2.0里有静态类?

  回复  引用    
#24楼  2006-01-19 17:34 | xxqq [未注册用户]
关于这个,你可以上我的博客上看看一篇文章,http://blog.csdn.net/xxqq0824

我还是贴在这吧,主要是讲静态变量在设计下和内存中的事。



静态变量,是属于类的,这个是挂在口边的,那么到是什么叫做属于类的呢?我认为,就是属于整个类的全体对象的.为类的全体对象所共有的。一个简单的比方,一个页面对象中,声明一个静态变量初始值为10,每个客户(即一个对象)访问一次页面,就会更改这个变量,A用户把这个变量更改成了12,B用户进来访问这个页面的时候又改变了这个变量,他会在12的基础再次改变,成了14,这个就是静态变量(比较感性的认识)。这个变量就是在全体对象间的共享。而如果是对象级的变量,他只能是在10的基础上又一次改变成了12,不会成为14。

静态构造函数是用来初始化类中的静态变量的。执行时间是在加载类时执行静态构造函数。(实例构造函数是在初始化对象时调用的)。静态构造函数是没有修饰符的。因为它只是由系统在加载类时自动执行的。而且静态构造函数是不能带有任何参数的。(因为要是给他传递值,是传递什么呢?)。

总之,静态变量是与类一起,存活在栈区的栈头上的,而对象们,是存活在栈头以下,每个对象,clr为其开辟一个线程,在栈区存有其地址,在堆区存储其实际内容(方法例外,方法是存在于栈区,堆区对象内的方法,只是一个方法的指针,指向方法在栈区的地址。)在栈头的静态变量,为每个对象所共享,当然,在创建对象的时候,是以类为模板,刻画出一个对象。。。。


  回复  引用    
#25楼  2006-01-24 19:54 | Darkangle [未注册用户]
我觉得不会吧,在微软的企业程序块里面都是用的静态方法,在PET SHOP里面也使用了这个程序集,但心这个是不是有点杞人忧天?
  回复  引用    
#26楼  2006-02-18 22:32 | 笨佬(熊) [未注册用户]
各位大哥先别担心这个了,能告诉我什么时候用实例什么时候用累成员吗?
  回复  引用    
#27楼  2006-05-07 09:23 | key [未注册用户]
谢谢各位大峡,我想我该该该我程序了。
  回复  引用    
#28楼  2006-05-08 17:29 | 跳蚤 [未注册用户]
小伙子,你多虑了。找你上面的程序是不会出现并发冲突的。因为每个线程都有独立的堆栈空间,比如:
static void getDataSet(){
DataSet ds=new DataSet();//这个变量分配到当前线程的堆栈空间,别的线程是无法访问的。
}
但是这种情况你就需要特别注意了:
int i=0;
static void getDataSet(){
if(i==0) return new DataSet();
}
  回复  引用    
#29楼  2006-07-21 11:03 | 游客不平 [未注册用户]
@idior

最讨厌你这种人说话的口气!!垃圾!!自以为是!
  回复  引用    
#30楼  2006-10-25 13:26 | 游客 [未注册用户]
学到了不少,大家说的都很有道理。
就鄙视idior,垃圾一个,别的没什么好说的
  回复  引用    
#31楼  2006-11-16 08:28 | qzq [未注册用户]
静态方法只要不修改共享的变量(包括参数是同一个对象,静态成员,全局属性等),且该共享的变量不被其他方法同时修改的话,只用参数和局部变量,是可重入的,即线程安全,不会出问题的。


  回复  引用    
#32楼  2007-01-23 12:07 | cantops [未注册用户]
呵呵,学到了, 我也一直在思考这些个问题!
  回复  引用    
#33楼  2007-01-30 13:16 | lilizizi [未注册用户]
静态方法
原理就是共享代码段
共享代码段不会产生任何问题
因为代码段都是给CPU作为"读取"用的,除非你进行恶意"修改"运行时的代码段
所以静态方法是可以放心使用的

静态变量
原理就是共享数据段
同上 只要没有进行"写入"操作就不会产生问题 但是数据通常都是用于读和写 所以静态变量要注意使用
  回复  引用    
#34楼  2007-07-18 13:08 | lele [未注册用户]
@跳蚤
你说得还比较容易明白

  回复  引用    
#35楼  2007-09-25 09:19 | 陈进业 [未注册用户]
我在实际开发(Web)中也遇到类似的情况,好象真的不太安全,有冲突.不知道是用静态方法还是Session,搞得成个项目好多地方要重新改动,所以现在不敢用表态方法+Session了.
  回复  引用    
#36楼  2007-12-08 10:51 | Vincent Luo      
似乎对静态与非静态有点了解了

以前我还很少用static呢
  回复  引用  查看    
#37楼  2008-04-08 11:03 | 213 [未注册用户]
idor
注意说话的口气啊,这可是和谐社会,不要起矛盾
  回复  引用    
#38楼  2008-04-22 23:20 | 汉广      
每一个线程都有自己独立的堆栈?
我得回去翻翻操作系统了
  回复  引用  查看    

标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      


相关链接: