多执行绪

多执行绪

在一个程式中,这些独立运行的程式片断叫作“执行绪”(Thread),利用它编程的概念就叫作“多执行绪处理”。

  • 中文名称
    多执行绪
  • 外文名称
    multithreading
  • 用途
    实现多个执行绪并发执行的技术
  • 对象
    电脑

​简要介绍

在电脑编程中,一个基本的概念就是同时对多个任务加以控製。许多程式设计问题都要求程式能够停下手头的工作,改为处理其他一些问题,再返回主进程。可以通过多种途径达到这个目的。最开始的时候,那些掌握机器低级语言的程式员编写一些“中断服务常式”,主进程的暂停是通过硬体级的中断实现的。尽管这是一种有用的方法,但编出的程式很难移植,由此造成了另一类的代价高昂问题。中断对那些即时性很强的任务来说是很有必要的。但对于其他许多问题,只要求将问题划分进入独立运行的程式片断中,使整个程式能更迅速地回响使用者的请求。

多执行绪

最开始,执行绪只是用于分配单个处理器的处理时间的一种工具。但假如作业系统本身支持多个处理器,那麽每个执行绪都可分配给一个不同的处理器,真正进入“并行运算”状态。从程式语言的角度看,多执行绪操作最有价值的特徵之一就是程式员不必关心到底使用了多少个处理器。程式在逻辑意义上被分割为数个执行绪;假如机器本身安装了多个处理器,那麽程式会运行得更快,毋需作出任何特殊的调校。根据前面的论述,大家可能感觉执行绪处理非常简单。但必须注意一个问题:共享资源!如果有多个执行绪同时运行,而且它们尝试访问相同的资源,就会遇到一个问题。举个例子来说,两个执行绪不能将信息同时传送给一台印表机。为解决这个问题,对那些可共享的资源来说(比如印表机),它们在使用期间必须进入锁定状态。所以一个执行绪可将资源锁定,在完成了它的任务后,再解开(释放)这个锁,使其他执行绪可以接着使用同样的资源。

多执行绪是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用效率来提高系统的效率。执行绪是在同一时间需要完成多项任务的时候实现的。

执行绪概念

定义

英文:Thread

每个正在系统上运行的程式都是一个进程。每个进程包含一到多个执行绪。进程也可能是整个程式或者是部分程式的动态执行。执行绪是一组指令的集合,或者是程式的特殊段,它可以在程式裏独立执行。也可以把它理解为代码运行的上下文。所以执行绪基本上是轻量级的进程,它负责在单个程式裏执行多任务。通常由作业系统负责多个执行绪的调度和执行。

多执行绪

执行绪是程式中一个单一的顺序控製流程.在单个程式中同时运行多个执行绪完成不同的工作,称为多执行绪.

执行绪和进程的区别在于,子进程和父进程有不同的代码和资料空间,而多个执行绪则共享资料空间,每个执行绪有自己的执行堆叠和程式计数器为其执行上下文.多执行绪主要是为了节约CPU时间,发挥利用,根据具体情况而定. 执行绪的运行中需要使用电脑的记忆体资源和CPU。

执行绪好处

·使用执行绪可以把佔据长时间的程式中的任务放到后台去处理

·使用者介面可以更加吸引人,这样比如使用者点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度

·程式的运行速度可能加快

·在一些等待的任务实现上如使用者输入、档案读写和网路收发资料等,执行绪就比较有用了。在这种情况下可以释放一些珍贵的资源如记忆体佔用等等。

还有其他很多使用多执行绪的好处,这裏就不一一说明了。

执行绪缺点

·如果有大量的执行绪,会影响性能,因为作业系统需要在它们之间切换。

·更多的执行绪需要更多的记忆体空间。

·执行绪可能会给程式带来更多“bug”,因此要小心使用。

·执行绪的中止需要考虑其对程式运行的影响。

·通常块模型资料是在多个执行绪间共享的,需要防止执行绪死锁情况的发生。

一些执行绪模型的背景

可以重点讨论一下在Win32环境中常用的一些模型。

·单执行绪模型 

在这种执行绪模型中,一个进程中只能有一个执行绪,剩下的进程必须等待当前的执行绪执行完。这种模型的缺点在于系统完成一个很小的任务都必须佔用很长的时间。

·块执行绪模型(单执行绪多块模型STA)

这种模型裏,一个程式裏可能会包含多个执行的执行绪。在这裏,每个执行绪被分为进程裏一个单独的块。每个进程可以含有多个块,可以共享多个块中的资料。程式规定了每个块中执行绪的执行时间。所有的请求通过Windows讯息伫列进行串列化,这样保证了每个时刻只能访问一个块,因而只有一个单独的进程可以在某一个时刻得到执行。这种模型比单执行绪模型的好处在于,可以回响同一时刻的多个使用者请求的任务而不只是单个使用者请求。但它的性能还不是很好,因为它使用了串列化的执行绪模型,任务是一个接一个得到执行的。

·多执行绪块模型(自由执行绪块模型)

多执行绪块模型(MTA)在每个进程裏只有一个块而不是多个块。这单个块控製着多个执行绪而不是单个执行绪。这裏不需要讯息伫列,因为所有的执行绪都是相同的块的一个部分,并且可以共享。这样的程式比单执行绪模型和STA的执行速度都要快,因为降低了系统的负载,因而可以最佳化来减少系统idle的时间。这些应用程式一般比较复杂,因为程式员必须提供执行绪同步以保证执行绪不会并发的请求相同的资源,因而导致竞争情况的发生。这裏有必要提供一个锁机製。但是这样也许会导致系统死锁的发生。

进程和执行绪都是作业系统的概念。进程是应用程式的执行实例,每个进程是由私有的虚拟地址空间、代码、资料和其它各种系统资源组成,进程在运行过程中建立的资源随着进程的终止而被销毁,所使用的系统资源在进程终止时被释放或关闭。

执行绪是进程内部的一个执行单元。系统建立好进程后,实际上就啓动执行了该进程的主执行执行绪,主执行执行绪以函式地址形式,比如说main或WinMain函式,将程式的啓动点提供给Windows系统。主执行执行绪终止了,进程也就随之终止。

每一个进程至少有一个主执行执行绪,它无需由使用者去主动建立,是由系统自动建立的。使用者根据需要在应用程式中建立其它执行绪,多个执行绪并发地运行于同一个进程中。一个进程中的所有执行绪都在该进程的虚拟地址空间中,共同使用这些虚拟地址空间、全局变数和系统资源,所以执行绪间的通讯非常方便,多执行绪技术的套用也较为广泛。多执行绪可以实现并行处理,避免了某项任务长时间佔用CPU时间。要说明的一点是,目前大多数的电脑都是单处理器(CPU)的,为了运行所有这些执行绪,作业系统为每个独立执行绪安排一些CPU时间,作业系统以轮换方式向执行绪提供时间片,这就给人一种假象,好象这些执行绪都在同时运行。由此可见,如果两个非常活跃的执行绪为了抢夺对CPU的控製权,线上程切换时会消耗很多的CPU资源,反而会降低系统的性能。这一点在多执行绪编程时应该注意。Win32 SDK内置函式支持多执行绪的程式设计,并提供了作业系统原理中的各种同步、互斥和临界区等操作。Visual C++ 6.0中,使用MFC类库也实现了多执行绪的程式设计,使得多执行绪编程更加方便。

实际意义

一个採用了多执行绪技术的应用程式可以更好地利用系统资源。其主要优势在于充分利用了CPU的空闲时间片,可以用尽可能少的时间来对使用者的要求做出回响,使得进程的整体运行效率得到较大提高,同时增强了应用程式的弹性。更为重要的是,由于同一进程的所有执行绪是共享同一记忆体,所以不需要特殊的资料传送机製,不需要建立共享存储区或已分享档案,从而使得不同任务之间的协调操作与运行、资料的互动、资源的分配等问题更加易于解决。

执行绪同步

在多执行绪套用中,考虑不同执行绪之间的资料同步和防止死锁。当两个或多个执行绪之间同时等待对方释放资源的时候就会形成执行绪之间的死锁。为了防止死锁的发生,需要通过同步来实现执行绪安全。在Visual Basic.NET中提供了三种方法来完成执行绪的同步。

代码域同步

使用Monitor类可以同步静态/实例化的方法的全部代码或者部分代码段。

手工同步

可以使用不同的同步类(诸如WaitHandle, Mutex, ReaderWriterLock, ManualResetEvent, AutoResetEvent 和Interlocked等)建立自己的同步机製。这种同步方式要求你自己手动的为不同的域和方法同步,这种同步方式也可以用于进程间的同步和解除由于对共享资源的等待而造成的死锁。

上下文同步

使用SynchronizationAttribute为ContextBoundObject对象建立简单的,自动的同步。这种同步方式仅用于实例化的方法和域的同步。所有在同一个上下文域的对象共享同一个锁。

虽然多执行绪能给大家带来好处,但是也有不少问题需要解决。例如,对于像磁碟驱动器这样独佔性系统资源,由于执行绪可以执行进程的任何代码段,且执行绪的运行是由系统调度自动完成的,具有一定的不确定性,因此就有可能出现两个执行绪同时对磁碟驱动器进行操作,从而出现操作错误;又例如,对于银行系统的电脑来说,可能使用一个执行绪来更新其使用者资料库,而用另外一个执行绪来读取资料库以回响储户的需要,极有可能读资料库的执行绪读取的是未完全更新的资料库,因为可能在读的时候只有一部分资料被更新过。使隶属于同一进程的各执行绪协调一致地工作称为执行绪的同步。MFC提供了多种同步对象,下面我们只介绍最常用的四种:

临界区(CCriticalSection)

事件(CEvent)

互斥量(CMutex)

信号量(CSemaphore)

通过这些类,可以比较容易地做到执行绪同步。

相关信息

多执行绪在NET裏如何工作

在本质上和结构来说,.NET是一个多执行绪的环境。有两种主要的多执行绪方法是.NET所提倡的:使用ThreadStart来开始你自己的进程,直接的(使用ThreadPool.QueueUserWorkItem)或者间接的(比如Stream.BeginRead,或者调用BeginInvoke)使用ThreadPool类。一般来说,你可以"手动"为长时间运行的任务建立一个新的执行绪,另外对于短时间运行的任务尤其是经常需要开始的那些,进程池是一个非常好的选择。进程池可以同时运行多个任务,还可以使用架构类。对于资源紧缺需要进行同步的情况来说,它可以限製某一时刻只允许一个执行绪访问资源。这种情况可以视为给执行绪实现了锁机製。执行绪的基类是System.Threading。所有执行绪通过CLI来进行管理。

·建立执行绪:

建立一个新的Thread对象的实例。Thread的构造函式接受一个参数:

Thread DummyThread = new Thread( new ThreadStart(dummyFunction) );

·执行执行绪:

使用Threading命名空间裏的start方法来运行执行绪:

DummyThread.Start ();

·组合执行绪:

经常会出现需要组合多个执行绪的情况,就是当某个执行绪需要其他执行绪的结束来完成自己的任务。假设DummyThread必须等待DummyPriorityThread来完成自己的任务,只需要这样做:

DummyPriorityThread.Join() ;

·暂停执行绪:

使得执行绪暂停给定的秒

DummyPriorityThread.Sleep(

·中止执行绪:

如果需要中止执行绪可以使用如下的代码:

DummyPriorityThread.Abort();

·同步

经常会遇到需要线上程间进行同步的情况,下面的代码给出了一些方法:

using System;

using System.Threading;

namespace SynchronizationThreadsExample

{

class SynchronizationThreadsExample

{

private int counter = 0;

static void Main( )

{

SynchronizationThreadsExample STE = new SynchronizationThreadsExample();

STE.ThreadFunction( );

}

public void ThreadFunction ( )

{

Thread DummyThread = new Thread( new ThreadStart(SomeFunction)) ;

DummyThread.IsBackground=true;

DummyThread.Name = "First Thread";

DummyThread.Start( );

Console.WriteLine("Started thread ", DummyThread.Name);

Thread DummyPriorityThread = new Thread( new ThreadStart(SomeFunction) );

DummyPriorityThread.IsBackground=true;

DummyPriorityThread.Name = "Second Thread";

DummyPriorityThread.Start( );

Console.WriteLine("Started thread ", DummyPriorityThread.Name);

DummyThread.Join( );

DummyPriorityThread.Join( );

}

public void SomeFunction( )

{

try

{

while (counter < 10)

{

int tempCounter = counter;

tempCounter ++;

Thread.Sleep(1);

counter = tempCounter;

Console.WriteLine( "Thread . SomeFunction: "+Thread.CurrentThread.Name+counter);

}

}

catch (ThreadInterruptedException Ex)

{

Console.WriteLine( "Exception in thread "+Thread.CurrentThread.Name);

}

finally

{

Console.WriteLine( "Thread Exiting. "+Thread.CurrentThread.Name);

}

}

}

}

·使用Interlock

C#提供了一个特殊的类叫做interlocked,就是提供了锁机製的实现,可以加入如下的代码实现锁机製:

Interlocked.SomeFunction (ref counter);

·使用锁

这是为了锁定代码关键区域以进行同步,锁定代码如下:

lock (this){ Some statements ;}

·使用Monitor

当有需要进行执行绪管理的时候可以使用:

Monitor.Enter(this);

其他也有一些方法进行管理,这裏就不一一提及了。

执行绪的缺点

执行绪自然也有缺点,以下列出了一些:

·如果有大量的执行绪,会影响性能,因为作业系统需要在他们之间切换;

·更多的执行绪需要更多的记忆体空间

·执行绪会给程式带来更多的bug,因此要小心使用

·执行绪的中止需要考虑其对程式运行的影响

·通常块模型资料是在多个执行绪间共享的,需要一个合适的锁系统替换掉资料共享

多执行绪在JAVA裏面的套用

Java对多执行绪的支持是非常强大的,他禁止掉了许多的技术细节,让我们可以轻松的开发多执行绪的应用程式。

Java裏面实现多执行绪,有2个方法

1 继承 Thread类

class MyThread extends Thread {

public void run() {

// 这裏写上执行绪的内容

}

public static void main(String[] args) {

// 使用这个方法啓动一个执行绪

new MyThread().start();

}

}

2 实现 Runnable接口

class MyThread implements Runnable{

public void run() {

// 这裏写上执行绪的内容

}

public static void main(String[] args) {

// 使用这个方法啓动一个执行绪

new Thread(new MyThread()).start();

}

}

一般鼓励使用第二种方法,因为Java裏面只允许单一继承,但允许实现多个接口。第二个方法更加灵活。

Intel的多执行绪技术   HT

定义

超执行绪(HT)是英特尔所研发的一种技术,于2002年发布。超执行绪的英文是HT技术,全名为Hyper-Threading,中文又名超执行绪。超执行绪技术原先只套用于Xeon处理器中,当时称为Super-Threading。之后陆续套用在Pentium 4中,将技术主流化。早期代号为Jackson。

特点

通过此技术,英特尔成为第一间公司实现在一个实体处理器中,提供两个逻辑执行绪。之后的Pentium D纵使不支援超执行绪技术,但就集成了两个实体核心,所以仍会见到两个逻辑执行绪。超执行绪的未来发展,是提升处理器的逻辑执行绪,英特尔有计画将8核心的处理器,加以配合超执行绪技术,使之成为16个逻辑执行绪的产品。

英特尔表示,超执行绪技术让(P4)处理器增加5%的裸晶面积,就可以换来15%~30%的效能提升。但实际上,在某些程式或未对多执行绪编译的程式而言,超执行绪反而会降低效能。除此之外,超执行绪技术亦要作业系统的配合,普通支援多处理器技术的系统亦未必能充分发挥该技术。例如Windows 2000,英特尔并不鼓励使用者在此系统中利用超执行绪。原先不支援多核心的Windows XP Home Edition却支援超执行绪技术。

AMD   下一代处理器考虑多执行绪技术

Bulldozer“推土机”

近日据相关讯息透露,在HotChips会议上,AMD宣布下一代代号为Bulldozer“推土机”的处理器架构将採用单核多执行绪技术(multi-threadingtechnology),类似于Intel着名的超执行绪技术.

AMD没有透露有关其多执行绪能力和更多的细节,只说推土机处理器将在2011年推出,支持单核多执行绪技术.不过,AMD的做法和Intel的 HT是不同的,更类似于Sun的同步多执行绪技术(SimultaneousMulti-Threading),由1个物理核心扩展到4个执行绪.“推土机扩展出的单核心多执行绪技术和Intel的超执行绪採用的是不同方式.”AMD的代表PatConway也证实了这一点. 有趣的是,早些时候AMD还表示暂不考虑SMT或其他多执行绪技术,并将它套用在当下的处理器中.然而,AMD也认同步多执行绪是未来处理器产品大幅提升性能的必要特征.

推土机是AMD下一代微架构的处理器,事实上,它将是AMD自2003年后第一次对处理器架构进行重大改变.预计新一代的处理器将提供远高于目前产品的高性能,同时也加入SSE5指令集.

首款推土机系列桌面处理器代号为Orochi,将会拥有超过4个以上的处理器核心,8M以上的快取并支持DDR3记忆体,基于32nm工艺.伺服器版处理器代号为Valencia和Interlagos,这两款处理器将会拥有6、8以及12个处理器核心.

AMD至今从未採用过同步多执行绪(SMT)也就是Intel所称的超执行绪技术。虽然这样的技术在当年的P4时代显得并无实际用途,但到了现在,越发普及的多执行绪环境让超执行绪重新焕发了青春。

发展前景

以目前的套用环境来看,超执行绪技术可以让一些特定应用程式显着提速达10到15%。除了Intel的在Nehalem、Atom等中引入的超执行绪,无论IBM的Power系列,Sun的T1/T2/Rock系列等处理器架构都套用了类似的SMT同步多执行绪技术,用少量的电晶体带来大幅度的多执行绪性能提升。

一位AMD工程师日前向媒体坦诚,不支持单核多执行绪技术让Opteron处理器看起来性能比不上Intel的低端Xeon。据称,AMD内部高层已经承认,没有早早引入此类技术是一项技术选择上的失误。

不过,AMD副总裁兼伺服器工作站业务总经理Patrick Patla接受採访时,并没有明确透露单核多执行绪技术的未来,而是继续重申已经公布的Opteron路线图:“如果你看一下我们路线图以及我们在多执行绪处理器市场的表现就会知道,我们相信每条执行绪都拥有完整的核心是目前的最佳选择。2010年,我们就会推出12核处理器,2011年16核。我们相信未来几年内我们就能够完善支持48或64执行绪环境,让我们来看看2012到2013年会带来些什麽吧。”

既然2011年才是16核,那麽2012到2013直接跳跃到48甚至64核似乎并不是那麽正常。另外,Patrick Patla前面句句都在讲“核”,而到了后面又变成了“执行绪”,似乎就在暗示到时AMD可能会採纳单核多执行绪技术。    

相关词条

相关搜索

其它词条