《第9章、多线程编程.docx》由会员分享,可在线阅读,更多相关《第9章、多线程编程.docx(22页珍藏版)》请在优知文库上搜索。
1、第9举多线程编程本章0标在前两章中.读者主要学习了有关进程控制和进程间通信的开发,这些都是UnUX开发的根底.在这一章中将学习轻最线进程战程的开发,由于线程的高效性和可操作性,在大型程序开发中运用得非常.广泛,带望读者能够很好地掌握.掌握1.inux中线程的根本概念口拿握1.inUX中线程的创立及使用U掌1.inux中线在属住的设五1.J能够以立场写多蛾程程序1.1.9.1 1.inUX线程概述线程概述前面已经提到,进程是系统中程序执行和资源分配的根本单位。得个进程都拥行自己的数据段、代码段和堆枝段.这就造成了进程在进行切换等操作时挪需要彳f比拟熨杂的上下文切换等动作.为了进一步就少处理机的空
2、转时间,支持多处理涔以及或少上下文切换开销,进程在演化中出现了另一个概念线程。它是进程内独立的一条运行路线,处理潜调度的最小单元也可以称为轻量级进程.线程可以对进程的内存空间和资源进行访问,并与同一进程中的其他线程共享.因此,级程的上下文切换的开销比创立进程小很多。同进程一样,线程也将相关的执行状态和存储变域放在线程控制表内.一个进程可以有多个线程,也就是有多个线程控制表及堆栈存放器.但却共享一个刖户地址空间.要注意的是由于线程共享了进程的资源和地址空间,因此,任何战程对系统资源的操作都会给其他规程带来影响。由此可知,多线;程中的同步是非常界要的问题。在多战程系统中,进程与进程的关系如图9所示
3、.图9.1进程与我桂关系线程机制的分类和特性双程按照其时度拧可以分为用户级线程和核心级线程两种-(I)用户级规程。用户级战程主要解决的是上下文切换的问题,它的调度算法和调度过程全部由用户自行选择决定.在运行时不需要特定的内核支持.在这里,操作系统往往会提供一个用户空间的税程诲,该线程际提供了践程的创立、调度和微错等功能,而内核仍然仅对进程诳行管理。如果一个进程中的某一个战程调用了一个阻塞的系统调用函数,那么该进程包括该进程中的其他所有线程也同时被阻塞.这种用户级线程的主要缺点是在一个诳程中的多个线程的调度中无法发挥多处埋器的优势.(2)轻埴奴进程。轻量级进程是内核支持的用户线程,是内核线程的一
4、种抽象对我.每个线程拥有一个或多个轻疑被税程,而每个轻量级线程分别被绑定在一个内核战程上。内核战程。这种线程允许不同进程中的线程按照同一相时优先调度方法进行两度,这样就可以发挥多处理器的并发优势.现在大多数系统都采用用户级战程与核心级战程并存的方法。一个用户级线程Ur以对应一个或几个核心级线程,也就是“一对一”比“多对一”模型.这样既可满足多处理机系统的需要也可以最大限度地战少两度开销.使用战程机制大大加快上下文切换速度而且节省很多资源,但是因为在用户态和内核态均要实现询度管抻,所以会增加实现的更公度和引起优先级朝转的可能性.一个多线程程序的同步设计与调试也会增加程序实现的难度”9.2 1.i
5、nUX线程编程线程根本编程这里要讲的线程相关操作都是用户空间中的规程的操作.在1.inux中,一般Pthread线程库是一套通用的规程阵,是由POSIX提出的,因此具有很好的可移植性.(1)函数说明.创立规程实际上就是确定调用该线程函数的入口点,这里通例使用的函数是P1.hrea1.Crea在践程创立以后,就开始运行相关的戏程函数,在该函数运行完之后,该线程也就退出了.这也是战程退出一种方法.另一种退出线程的方法是使用的数p可以用于将当前线程拄起来等待规程的结束.这个函数是一个规程阻我的函数,调用它的函数将一直等待到被簪待的代程结束为止,当南救返回时,被等待线程的资源就被收回。前面已提到线程调
6、用pthreadfXitO函数主动终止自身线程.但是在很多线程应用中,羟常会遇到在别的线程中要终止另一个线程的执行的何时。此时调用Pthrea1.CanCe1.o函数实现这种功能,但在被取消的线程的内部需要调用Pthtra1.scICaneC1()函数和phrea1.sCICanCdIyPC()的数设置自己的取消状态,例如被取消的线程接收到另一个线程的取消请求之后,是接受还是忽略这个请求:如果接受.是立刻进行终止操作还是等待某个函数的调用等.(2)函数格式。表9.1列;I;/PthrCad_crcatc()函数的谱法要点.表。PthrWUI_CrVat0由S1.t语法要点所需央文件inc1.u
7、deft5!ui1.P1.hiYac1.crvaM(p1.htuad,1.thread,pciuvad.a(1.rJ4a1.1.r.void*(tstat.rcHJi)(x)id*).void*arg由政传入Ihrsdr规程标识符Jftaiir:(共区体设JH参见小节),为常取为NU1.1.Urt/uutine:找程雨数的起始地址.是一个以指向vuid的指针作为警致和返H1.ft的函数指针I1.rgIi2Ma11.roinc(Kft-IaiSiSI成功20(ft出楮:返回错限码表9.2列IH了P1.hrCad_exi1.()函数的语法要点。表9.2PthrVad_e、it()函数语法妾点所格头
8、文件Windude函数原型Voidpthrc;wi_cxit(wid*c1.va1.)Ffi8(传入位revah线和给束时的iM(i1.Id1.HttjFfitttaP1.hreHdJoEO来获取表93列出了P1.hreadjoi110函数的语法要点。表。与pdEdJinO函效语法要点所需为文件*inc1.udcin(PthrcJcin(pthrcjth.Veid*thrcnd.reium)th等待线程的标识符函数传入值thicadjCtUm:用户定义的折计,用来存储被等特级利结束时的返H1.W(不为Nu1.1.时)的散返同伙成爪0btft返回错误码ii9.4列出了PthrCa1.CanCdo
9、函数的语法要点.表0”,Pt1.MTX1.mc*T()函数诘法要点所需头文件析IKhKfc的致原案intphrcad-cactphrcudjth)函数传入值h)要取消的线程的标识符函数返回成功I0(ftH1.ffi1.返回错误码(3)函数使用.以下实例中创立了3个战程,为了更好地描述燃程之间的并行执行,让3个战程重用同一个执行函数。每个线程都有S次循环(可以存成5个小任务),每次循环之间会随机等待I-IoS的时间意义在于模拟每个任分的到达时间是时机的,并没仔任何特定规律./*thread.c*/inc1.udeinc1.ude!inc1.ude”战.程金、/每个慢程中的小任务数“小任务之间的最
10、大defineTHE;forcount-0;countREPEATNUMBER;countde1.ay-ti-intjrand11*DE1.AY_TIME_1.EVE1.SZ;pthread_cxit(NU1.1.);)intEoirHvoidI(pthread-tthrcad(THREAD_NUMBR;intno-Orres;voidthrd-ret;8rand(tire(NU1.1.);forno-0;noTHREAD-NUMBER;no)(/A锁立多线程-/espthreadcreate(6threadnozNU1.1.,trdefuncf(void*)no);ifres!-O)(rin
11、tfIwCreatethread%dta1.1.edn,fno);exit;forno-O;no;)e1.serintf1.,Thread、d:oinfai1.ednw,no);returnO;以下是程序运行结果,可以看H1.绿个战程的运行和结束是独立与并行的。S./threadCreatetreadssuccessWaitingforthreadstofinish.ThreadOisstartingThreadThread1isstarting2isstartingThread1:jobOde1.ay.6Thread2:jobOde1.ayM6ThreadO:JobOde1.ay9Thread1:job1de1.ay6Thread2:job1de1.ayarBThreadO:job1de1.ay8Thread2:Job2de1.ayB3ThreadO:job2de1.ay3Thread2:job3de1.ayW3ThreadThread2:job42finishedde1.ay=1Thread1:Job2de1.ay10Thread1:job3de1.ay.4ThreadThread1:job41finishedde1.ay=1ThreadO:job3de1.ayB9ThreadThreadO: