【C#】编程点滴:关于Static的思考

在ADO.NET数据访问层我们通常会将数据库连接字符串写成这样private static
readonly string _conStr =
"server=.;database=Product;uid=sa;pwd=sa";、这样的情况很多,比如单例模式。可能是出于约定俗成吧,也可能是习惯了"海淘"人家的,很多东西也没深入去考虑为什么要这样写(说我自己)。或许是看人家都这么写。那么为什么要用static来修饰?为什么还要加上readonly?又为什么说静态的是线程安全的呢?为了解释这些问题。我想我还得必须了解static的"前世今生",也就是为什么要有static这个关键字了。

先来看msdn关于静态类和静态类成员的解释:

静态类和类成员用于创建无需创建类的实例就能够访问的数据和函数。静态类成员可用于分离独立于任何对象标识的数据和行为:无论对象发生什么更改,这些数据和函数都不会随之变化。当类中没有依赖对象标识的数据或行为时,就可以使用静态类。

言简意赅。不过有点抽象。从这里似乎看不出,它和线程安全有什么直接的关系。那么我们来看一篇人家写的文章吧(为了阅读方便。我就直接贴出来了):

在.Net中,Static会经常和线程的东西扯在一起。写的代码是不是线程安全呢?好多程序员都在想,不过,有时候随便就放过了。真正出问题的时候再想。其实,如果程序员一开始就明白这里面的机制,也许,编写的代码质量会更加的高。也少些线程安全的烦问题。事实上,了解线程安全的机制后,你会发现,这原来是很简单的事情,只是很多人不愿意去了解线程(仔细一想,有的时候自己我(不是文章的作者)何尝不是这样)。因为对于普通的程序员,线程的东西真是不好玩的,也不太过瘾,同时好容易出错。生活中的例子顾客一次买了10个产品去收银处交钱,一般来说,收银处的框台应该很多的,顾客可以选一个人少的结帐就行了。而收银员可以一个个顾客地处理。这当然是有条不紊的事了。实际上,每个收银员就是一个线程,如果一个框台对于一个收银员的话,也就真是没有问题了。框台就是一个资源。

但是对于操作系统而言,资源往往是很宝贵的,要提供给多个收银员使用。即线程共享地使用资源。而操作系统的调度经常是没有道理的,也就是随意性很大。一时由收银员A操作,一时由收银员B操作。
试想想,收银员A,B都不能很好地做自己的事情,而且操作的数据会很混乱。也根本不知道对不对。不过,如果收银员A可以在一段时间内独占框台,事情也就会很容易了。这样虽然导致排队的用户很多,效率也低,但是每一个顾客的数据都处理正确的。
这其实就是线程安全的问题,如果一个线程把资源锁住了,别的线程在排除,数据就会很正确的。

Static代码例子
下面的代码,无论你使用多少的线程来控件(制),都是安全的。因为线程之间,不会共享什么资源,唯一相同的是使用了同一个逻辑。其实这是在破坏线程的前题方面下功夫,出现线程不安全的条件都没有了,那肯定就是线程安全的

class CheckoutLane
{
public static float GetTotal(Cart cart)
{
float total = 0;

for (int i = 0; i < cart.GroceryItems.Length; i++)
{
total += cart.GroceryItems[i].Price;
Thread.Sleep(100);
}
return total;
}
}


View
Code

而下面的代码,不是线程安全的,因为共享了static float
total;这个资源,而各个线程都被随机调用,可以任意修改total这个数据。这个,就正如多个收银员共享柜台,任意执行收银操作一样。

class CheckoutLane
{
static float total;

public static float GetTotal(Cart cart)
{
total = 0;

for (int i = 0; i < cart.GroceryItems.Length; i++)
{
total += cart.GroceryItems[i].Price;
Thread.Sleep(100);
}
return total;
}

}

下面的代码是线程安全的,使用了lock关键字,可以达到一个线程强占资源的效果。这时,synchLock就作为了共享的资源,被某一个线程锁住了。

class CheckoutLane
{
static float total;
static object synchLock = new object();

public static float GetTotal(Cart cart)
{
lock(synchLock)
{
total = 0;

for (int i = 0; i < cart.GroceryItems.Length; i++)
{
total += cart.GroceryItems[i].Price;
Thread.Sleep(100);
}
return total;
}
}
}

哈哈,人家的文章写得确实很不错。所以直接"舶来"品一下。这篇文章讲的很清楚。Static是线程安全的原因。这也给我提示为什么在类型的实例化的方面最好不要使用是static来修饰。因为使用它相当于将资源加上了锁。就像公共厕所,你占住了。别人就要等,特别是便池不够的时候。这当然会让别人感到很无奈。浪费了别人了时间。万一别人尿急了妮,是不是?这就是很多说的为什么使用static会对性能造成影响的原因了。但是也只有这样才能保证每一个人都很守秩序。要是大家随便乱闯,可就有走光的危险了。如果这个static修饰的变量是全局的我们往往给他加上readonly来修饰。因为static修饰的变量还是可以被重新赋值,而它又是被共享的了。加上readonly就是只读了,保证了数据的安全。

【C#】编程点滴:关于Static的思考,布布扣,bubuko.com

时间: 2024-11-08 12:24:43

【C#】编程点滴:关于Static的思考的相关文章

【ASP.NET】编程点滴 :ASP.NET身份验证

ASP.NET实际开发中身份验证 是一个不可回避的问题.在相当一段长的时间内,由于不求甚解,我对这个话题似懂非懂.今天就对它做个简单的小结. Authentication and Authorization(身份验证和授权) 在开始ASP.NET身份验证之前,我们必须了解两个概念:Authentication and Authorization Authentication是识别该用户的身份,换句话说,它检查特定用户是不是特定网站的用户,它回答了“Who are you”的问题. Authori

学习编程是否做笔记的思考

做编程是否做笔记的思考: 做笔记的目的是将来怕忘.什么东西是重要的怕将来忘掉?1.需要记得东西:你自己的体会.经验.这些东西怕忘了,需要记笔记.2.什么不用记: 网上.书上随手可得的东西,没必要花时间记. 语言只是一门工具,精通工具的唯一手段就是熟练使用. 此外,编程又是一门语言,语言就是要多练才能熟练掌握. 所以,通常来说,学编程的时候不需要做笔记. 回到学习一门新语言的问题.可以有两种办法检验你是否学会了一门新语言:你可以用这个语言,做个实际项目:或者你可以教别人学会这个语言. 注:主要是自

【WebForm】编程点滴:由文本框回车触发按钮点击事件想到的

在WebFomr中我们常常会需要实现这样一个功能:文本框回车时触发触发其他按钮的click事件.在JS中我们常常这样做: <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

.net 异步编程async &amp; await关键字的思考

C# 5.0引入了两个关键字 async和await,这两个关键字在很大程度上帮助我们简化了异步编程的实现代码,而且TPL中的task与async和await有很大的关系 思考了一下异步编程中的async & await关键字,对两个关键字尤其是await关键字一直很迷糊,因此深入思考了一下.首先借助的示例是:[你必须知道的异步编程]C# 5.0 新特性--Async和Await使异步编程更简单这是博客园一个大牛写的,自己也一直关注这个大神,不得不说,博客园大神很多,而且氛围也很好.我引入了其中

关于高性能网络编程的一些总结与思考

从IO说起 一直以来我很欣赏Google I/O大会,一方面是由于一些新技术与新产品的介绍让人兴奋,更重要的是我太爱这个名字了^_^,我觉得正好符合了我对整个互联网技术的浅薄思考与认识.I/O系统就是整个互联网的关键接口,整个互联网的底层就是I/O系统织成的抽象意义上的net,建立在物理线路之上.而网络编程显然是合理创造与利用I/O的重要工具.而以太网的TCP/UDP则在通常的网络编程中占据了核心的地位.本文主要基于Linux平台,其他如Windows NT以及一些Unix衍生版都提供了对应的解

Phone 7编程点滴

1. 修改文件名 1 public static void Move(string sourceFileName, string destFileName); 2.得到运行的EXE文件所在目录 1 /*函数功能: 获取程序所在路径 */ 2 public static string GetAppPath() 3 { 4 string usrdir; 5 usrdir = System.Reflection.Assembly.GetExecutingAssembly().GetName().Cod

Django1.8.6+Python3.4.3实践点滴——配置static

文件结构: 第一步:配置Settings.py STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR, "expressway/static"), ) 第二步:配置base.html {% load staticfiles %} #加载staticfiles <!DOCTYPE html> <html lang="zh-CN"> <head> <

编程中,static的用法详解

C++的static有两种用法:面向过程程序设计中的static和面向对象程序设计中的static.前者应用于普通变量和函数,不涉及类:后者主要说明static在类中的作用.一.面向过程设计中的static1.静态全局变量在全局变量前,加上关键字static,该变量就被定义成为一个静态全局变量.我们先举一个静态全局变量的例子,如下: #include<iostream> using namespace std; static int n;  //定义静态全局变量 void fn() { n++

对并发编程的相关总结与思考

内容包括,并发与并行,并发约束,并发下的集合类性能分析,并发相关包的概述,并发场景,并发总结 转载请注明出处:http://blog.csdn.net/supera_li/article/details/45198341 集合包 关于集合类的并发实现: http://blog.csdn.net/supera_li/article/details/39371087 下面是接口关系 1.接口Collection->List,Set List–>>ArrayList,LinkedList,Ve