ASP.NET网页编程之详解.NET编程过程当中的线程抵触
java的设计机制:首先产生一个中间码,第二部编译为本地(机器)码。这个机制有很大的缺点。看起来,将其lock起来后,就高枕无忧了,没有人能修正这个容器,但实践上这个容器不外是用一个ArrayList实例来完成的,假如某段代码绕过这个容器而间接操纵_list的话,则对这个容器工具lock也不成能包管容器不被修正了。1、甚么是线程抵触线程抵触实在就是指,两个或以上的线程同时对统一个共享资本举行操纵而酿成的成绩。
一个对照典范的例子是,用一个全局变量做计数器,然后开N个线程往完成某个义务,每一个线程完成一次义务就将计数器加一,直到完成100次义务。假如不思索线程抵触成绩,用相似上面的代码往做,则极可能会逾额完成义务,线程越多,完成义务次数超越100次的大概性就越年夜。
伪代码以下:
intcount=0;//全局计数器
voidThreadMethod()//运转在每一个线程的办法
{
while(true)
{
if(count>=100)//假如到达义务目标
break;//中止线程实行
DoSomething();//完成某个义务
count++;
}
}
//省略线程的创立等代码。
详细的,为何会逾额完成义务的缘故原由在这里我就不赘述了,这个例子在单线程情况中是相对不会逾额完成义务的。
固然,在这个例子中,将count++放到if语句中,大概能下降一些变乱产生的几率,但那不是相对的,换言之如许的程序不克不及根绝逾额完成义务的大概。
实在从线程抵触的界说中我们不难发明,要形成线程抵触有两个需要前提:多线程和共享资本。这两个前提中有一个不建立,就不成能产生线程抵触成绩。
以是,在单线程情况中,是不存在线程抵触的成绩的。不外很惋惜的是,我们的软件早已退化到了多历程多线程的时期,单线程的程序几近是不存在的,不管是WinForm仍是WebForm,程序运转的情况都是多线程的,而不管你本人是否是明白的开启了一个线程。
既然多线程是不成制止的,那末要制止线程抵触就只能从共享资本来开刀了。
2、线程平安的资本
假如人人常常看MSDN大概VS匡助中的.NET类库参考的话,就不难发明几近一切的范例都有这么一句话的形貌:“此范例的任何大众static(在VisualBasic中为Shared)成员都是线程平安的。但不包管一切实例成员都是线程平安的。”那末线程平安究竟是甚么意义?
实在线程平安很复杂,就是指一个函数(办法、属性、字段大概其余)在统一工夫被分歧线程利用,不会形成任何线程抵触的成绩。就说这个器材是线程平安的。
接上去来谈谈甚么样的资本是线程平安的。
之以是利用资本这个词,是由于线程抵触不单单会产生在共享的变量上,两个线程同时对统一个文件举行读写,两个程序同时用统一个端口与统一个地点举行通讯,城市形成线程抵触。只不外是操纵体系和帮我们和谐了这些抵触罢了。
一个线程平安的资本便是指,在分歧线程中利用不会招致线程抵触成绩的资本。
一个不克不及被改动的资本是线程平安的,好比说一个常量:
constdecimalpai=3.14159265;//C++:constdoublepai=3.14159265;
由于pai的值不成能被改动,以是在分歧的线程中利用也不会形成抵触。换言之它在分歧的线程中同时被利用和在一个线程中被利用是没有区分的,以是这个器材是线程平安的。
一样的,在.NET中,一个字符串的实例也是线程平安的,由于字符串的实例在.NET中也是不成以被改动的。一个字符串的实例一旦被创立,对其一切的属性、办法挪用的了局都是独一断定的,永久不会改动的。以是.NET类库参考中String范例才有:“此范例是线程平安的。”,与之相似的Type范例、Assembly范例,都是线程平安的。
但string的实例是线程平安的,却不代表string的变量是线程平安的,换言之,假定有一个静态变量:
publicstaticstringstr=“123”;
str不是线程平安的,由于str这个变量的字符串实例能够被任何线程修正。
再思索如许的例子:
publicstaticreadonlySqlConnectionconnection=newSqlConnection(“connectionString”);
固然connection自己固然是线程平安的,但connection的任何成员都不是线程平安的。
好比说,我在一个线程中对这个connection挪用了Open办法,然落后行查询操纵。但在统一时候,另外一个线程挪用了Close办法,这时候候,就呈现毛病了。
但,纯真的利用connection而不利用其任何成员,好比说if(connection!=null)如许的代码,是不存在线程抵触的。
线程平安的资本实在另有良多,在此纷歧一赘述。
关于.NETFramework的范例的成员来讲,只读的字段是线程平安的。
那末关于属性和办法来讲,怎样晓得是否是线程平安的?
3、线程平安的函数
由于属性和办法都是函数构成的,以是我们切磋一下甚么是线程平安的函数。
下面我们说到,线程抵触的需要前提是多线程和共享资本。那末假如一个函数内里没有利用任何大概共享的资本,那末就不成能呈现线程抵触,也就是线程平安的。好比说如许的函数:
publicstaticintAdd(inta,intb){
returna+b;
}
这个函数中所利用的一切的资本都是本人的部分变量,而函数的部分变量是贮存在仓库上的,每一个线程都有本人自力的仓库,以是部分变量不成能跨线程共享。以是如许的函数明显是线程平安的。
但值得注重的是:上面的函数不是线程平安的:
publicstaticvoidSwap(refinta,refintb)//C++:voidSwap(in&a,int&b)
{
intc=a;
a=b;
b=c;
}
由于ref的存在,使得函数的参数是按援用传送出去的,换言之a和b看起来是函数的部分变量,但实践上倒是函数表面的器材,假如这两个器材是另外一个函数的部分变量,倒也没有成绩,
假如这两个器材是全局变量(静态成员),就不克不及确保没有线程抵触了。而在上个例子中,a和b在传进函数之时,就做了一个拷贝的举措,以是传出去的a、b究竟是全局变量仍是静态成员都没有干系了。
一样,如许的函数也不是线程平安的:
publicstaticintAdd(INumbera,INumberb)//C++:intAdd(INumber*a,INumber*b);
{
returna.Number+b.Number;
//C++:returna->Number+b->Number;
}
缘故原由在于a和b固然是函数的外部变量没错,但a.Number和b.Number却不是,它们不存在于仓库上,而是在托管堆上,大概被其他线程变动。
但只利用部分变量的函数在.NET类库中是很少的,但.NET类库中仍是有那末多线程平安的函数,是为何呢?
由于,即便一个函数利用了共享资本,假如其所利用的共享资本都是线程平安的,则这个函数也是线程平安的。
好比说如许的函数:
privateconststringconnectionString=“…”;publicstringGetConnectionString()
{
returnconnectionString;
}
固然这个函数利用了一个共享资本connectionString,但由于这个资本是线程平安的,以是这个函数仍是线程平安的。
一样的,我们能够得出,假如一个函数只挪用线程平安的函数,只利用线程平安的共享资本,那末这个函数也是线程平安的。
这里有一个简单被疏忽的成绩,运算符。并非一切的运算符(特别是重载后的运算符)都是线程平安的。
4、互斥锁
偶然候我们不能不面临线程不平安的成绩,好比说在一入手下手提出来的谁人例子,多线程完成100次义务,我们如何才干办理这个成绩,一个复杂的举措就是给共享资本加上互斥锁。在C#中这很复杂。好比一入手下手的谁人例子:
publicstaticclassEnvironment{publicstaticintcount=0;//全局计数器
}
//…voidThreadMethod()//运转在每一个线程的办法
{
while(true)
{
lock(typeof(Environment))
{
if(count>=100)//假如到达义务目标
break;//中止线程实行
DoSomething();//完成某个义务
count++;}}}
经由过程互斥锁,使得一个线程在利用count字段的时分,其他一切的线程都没法利用,而被堵塞守候。到达了制止线程抵触的效果。
固然,如许的锁会使得这个多线程程序退步成同时只要一个线程在跑,以是我们能够把count++提早,使得lock的局限减少,如如许:
voidThreadMethod()//运转在每一个线程的办法{
while(true)
{
lock(typeof(Environment))
{
if(count++>=100)//假如到达义务目标
break;//中止线程实行
}
DoSomething();//完成某个义务
}}
最初来聊聊SyncRoot的成绩。
用.NET的必定会有良多伴侣狐疑,为何对一个容器加锁,必要如许写:
lock(Container.SyncRoot)
而不是间接lock(Container)
由于锁定一个容器其实不能包管不会对这个容器举行修正,思索如许一个容器:
publicclassCollection{
privateArrayList_list;
publicAdd(objectitem)
{
_list.Add(item);
}
publicobjectthis
{
get{return_list;}set{_list=value;}
}}
看起来,将其lock起来后,就高枕无忧了,没有人能修正这个容器,但实践上这个容器不外是用一个ArrayList实例来完成的,假如某段代码绕过这个容器而间接操纵_list的话,则对这个容器工具lock也不成能包管容器不被修正了。
也许C#刚上市的时候有些抄袭Java吧,但自从C#2.0上市之后,整个局面就扭转乾坤了,不但Java在模仿C#,而且他从来都没能跟得上C#的脚步。 我的意思是.net好用,从功能上来说比JAVA强还是很明显的。 使用普通的文本编辑器编写,如记事本就可以完成。由脚本在服务器上而不是客户端运行,ASP所使用的脚本语言都在服务端上运行,用户端的浏览器不需要提供任何别的支持,这样大提高了用户与服务器之间的交互的速度。 虽然在形式上JSP和ASP或PHP看上去很相似——都可以被内嵌在HTML代码中。但是,它的执行方式和ASP或PHP完全不同。在JSP被执行的时候,JSP文件被JSP解释器(JSPParser)转换成Servlet代码,然后Servlet代码被Java编译器编译成.class字节文件,这样就由生成的Servlet来对客户端应答。所以,JSP可以看做是Servlet的脚本语言(ScriptLanguage)版。 可以看作是VC和Java的混合体吧,尽管MS自己讲C#内核中更多的象VC,但实际上我还是认为它和Java更象一些吧。首先它是面向对象的编程语言,而不是一种脚本,所以它具有面向对象编程语言的一切特性。 asp.net空间的支持有:ASP.NET1.1/虚拟目录/MicrosoftFrontPage2000扩展/CDONTS,同时他的网站上也提供了Asp.net的使用详解和程序源代码,相信对使用ASP.NET编程的程序员来说会非常有用哦! 现在的ASP.net分为两个版本:1.1和2.0Asp.net1.1用VS2003(visualstudio2003)编程。Asp.net2.0用VS2005(visualstudio2005)编程。现在一般开发用的是VS2003。 现在主流的网站开发语言无外乎asp、php、asp.net、jsp等。 ASP在执行的时候,是由IIS调用程序引擎,解释执行嵌在HTML中的ASP代码,最终将结果和原来的HTML一同送往客户端。
页:
[1]