您的位置:首页 > 其它

多线程基本概念介绍(Introduction and Concepts)

2010-12-16 13:09 295 查看

一、多线程基本概念介绍(IntroductionandConcepts

C#支持通过多线程(multithreading),来并行的执行代码。每个线程都有一个独立的执行路径(executionpath)能和其它的线程同时运行。被操作系统和CLR直接创建的,运行在独立的一个线程的C#客户端程序(Console,WPF,orWindowsForms)叫做主线程,而额外创建的其它线程就是多线程。下面是一个简单的例子和输出。

所有的例子都引入以下的命名空间:

usingSystem;

usingSystem.Threading;



classThreadTest

{

staticvoidMain()

{

Threadt=newThread(WriteY);//Kickoffanewthread

t.Start();//runningWriteY()


//Simultaneously,dosomethingonthemainthread.

for(inti=0;i<1000;i++)Console.Write("x");

}

staticvoidWriteY()

{

for(inti=0;i<1000;i++)Console.Write("y");

}

}



下面是运行结果:





主线程创建一个新的线程t,用来运行WriteY()方法。同时主线程重复的打印字符“x”:





一旦一个线程启动了,该线程的
IsAlive属性就被置为true,一直到线程执行结束。当委托传递给构造函数执行完毕后,线程就结束了,
线程一旦执行结束,就不能在被重新启动。

CLR为每个线程的局部变量分配独立的栈空间。在下个例子中,我们将定义一个带有局部变量的例子,然后分别在主线程和新创建的线程中调用:

staticvoidMain()

{

newThread(Go).Start();//CallGo()onanewthread

Go();//CallGo()onthemainthread

}


staticvoidGo()

{

//Declareandusealocalvariable-'cycles'

for(intcycles=0;cycles<5;cycles++)Console.Write('?');

}




运行结果如下图:





因为局部变量都有独立的栈空间,所以打印出来的?号是十个。

如果线程之间有共同的引用,则它们共享数据。例如下面代码:

classThreadTest

{

booldone;


staticvoidMain()

{

ThreadTesttt=newThreadTest();//Createacommoninstance

newThread(tt.Go).Start();

tt.Go();

}


//NotethatGoisnowaninstancemethod

voidGo()

{

if(!done){done=true;Console.WriteLine("Done");}

}

}




因调用Go()方法的两个线程,拥有同一个引用,所以结果打印出来的是一个”Done”而不是两个。

静态变量以另外一种方式共享数据,下面是静态变量的例子:

classThreadTest

{

staticbooldone;//Staticfieldsaresharedbetweenallthreads


staticvoidMain()

{

newThread(Go).Start();

Go();

}


staticvoidGo()

{

if(!done){done=true;Console.WriteLine("Done");}

}

}




这个例子引出另外一个概念--线程安全。如果我们向下面那样修改Go方法,则"Done"被打印出来的次数是不确定的。

staticvoidGo()

{

if(!done){Console.WriteLine("Done");done=true;}

}



造成这个问题原因是:当一个线程执行打印语句,还没来得及修改done为true的时候,另一个线程又执行了打印语句。C#中提供lock机制来解决这一问题:

classThreadSafe

{

staticbooldone;

staticreadonlyobjectlocker=newobject();


staticvoidMain()

{

newThread(Go).Start();

Go();

}


staticvoidGo()

{

lock(locker)

{

if(!done){Console.WriteLine("Done");done=true;}

}

}

}



当两个线程竞争同一个临界资源(locker)的时候,其中一个线程被阻塞,直到另一个线程释放该资源。这种方式保证了某一时刻只有一个线程在使用临界资源。所有”Done”只被打印了一次。以这种方式,保证代码在多线程不确定环境中能够正确执行,就叫做线程安全。


临界资源是造成多线程中错误的主要原因,应该让其尽量的保持简单。


阻塞的线程是不会消耗CPU资源的!

1、JoinandSleep

你可以通过调用Join方法来等待其他线程执行结束。例如:

staticvoidMain()

{

Threadt=newThread(Go);

t.Start();

t.Join();

Console.WriteLine("Threadthasended!");

}


staticvoidGo()

{

for(inti=0;i<1000;i++)Console.Write("y");

}



在打印了1000次字符y后,紧接着就打印出了”Threadthasended!”这句话。你可以在Join方法的时候设置超时。如果正确执行则返回ture,如果超时则返回false。

Thread.Sleep方法让当前线程暂停一段时间:


Thread.Sleep(TimeSpan.FromHours(1));//sleepfor1hour

Thread.Sleep(500);//sleepfor500milliseconds



无论执行Join还是Wait方法,阻塞的线程都不会占用CPU资源。


Thread.Sleep(0)
是让当前线程进行一个让位动作。让其他线程在系统管理单元作出动作前有机会优先执行。

在Framework4.0中
Thread.Yield()也有同样的功能。



2、线程是如何工作的

在CLR中,线程是被一个叫做线程调度器的委托函数管理的。线程调度器保证所有的线程都分配用来执行的CPU时间,并保证阻塞的线程不占用CPU资源。

3、线程VS进程

线程和运行在你操作系统上的应用程序的进程有很大的相似性,就像多个进程并行的运行在计算机上一样,多个线程并行的运行在一个独立的进程上。进程与进程之间是完全隔离的,而线程只是在一定程度上是隔离的。运行在一个应用程序上的线程是共享堆内存的。这很大程度上也让线程变的很好用,比如:一个线程可以在后台取数据,另一个线程可以在前台呈现。

4、线程的正确使用和误用

多线程有很多用途,下面为常见的:

1、维护用户界面,让其可以及时响应。

另起一个线程来执行比较耗时的任务,让UI线程(Main线程),可以持续响应用户操作。

2、高效的利用CPU。

多线程是非常有用的,当一个线程等待另一台计算机或硬件的响应时。当一个线程执行某项任务而发生阻塞时,其他的线程能充分利用其他已经空闲的计算机。

3、并行程序设计。

在执行大量计算密集型任务时,通过采取分治策略,可以把任务量均摊在不同的线程上,这样可以加快任务的执行速度。

4、推理性执行(预测执行)。

在多核处理器中,有时你能通过预测需要处理的内容来改善性能。LINQPad使用这个技术加速创建新的查询。并行运行多个不同的算法来解决同一个任务。

允许多个请求被同步处理.这在你不知道哪个算法效率更高的情况下是非常有效的。(译者注:关于推理性执行请参考百度百科)

5、让请求可以并行执行。

在web服务器上,多个客户端请求同时到达,因此需要并行处理(如果你使用ASP.NET,WCF,WebServices,或者Remoting等技术,FrameWork会自动的为你创建线程)。这在客户端也是非常有用的(例如P2P的网络处理或者是来自一个用户的多个请求)。

多线程也会产生额外的问题。最大的问题是多线程会在一定程度上增加程序的复杂度。拥有很多线程就其本身来言并不复杂;复杂的是线程之间的相互作用和影响(特别是通过共享数据)。这些应用无论是否是有意的相互影响,都会导致较长的开发周期和持续出现不易发现的bugs。出于这个原因,应使这种影响减到最少,尽可能避免过度设计。本书主要是讨论如何处理这些复杂问题;而对于消除相互影响说的很少。


一个好的策略是把多线程的逻辑封装到一个可复用的类里,这个类可以独立地被检查和测试。Framework本身提供了很多高级别的封装类,这些我们将会在后边介绍到.Threading会在调度和转换线程时消耗资源和CPU时间(当活动线程超过CPU核数时),而且还有线程的创建和释放成本。多线程不是总是在加速你的应用程序-如果你使用的过多或者不恰当。例如,在磁盘和I/O被频繁调用时,使用两个工作线程按顺序运行任务,就比用10个线程同时运行要快。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐
章节导航