讲-线程进程安全_第1页
讲-线程进程安全_第2页
讲-线程进程安全_第3页
讲-线程进程安全_第4页
讲-线程进程安全_第5页
已阅读5页,还剩41页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第三章线程/进程安全进程和线程是两个范围不同的概念。进程是程序在计算机上的一次执行活动。运行一个程序,相当于启动了一个进程。进程是操作系统进行资源分配的单位,通俗地讲,是一个正在执行的程序。线程是进程中的一个实体,是被系统独立调度和分派的基本单位,它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。比如,一个在线播放软件,在播放歌曲的同时还可以进行下载,就可认为这两件工作由不同的线程完成。线程和进程的开发和相关操作,在程序设计中具有重要地位,线程和进程的安全和系统的安全息息相关。对于不够熟练的程序员来说,很容易出现安全隐患,而这些安全问题又具有不间断发生,难于调试等特点。一般说来,线程的安全性主要来源于其运行的并发性和对资源的共享性;进程的安全性主要在应用级别,在于其对系统的威胁性,不过对于系统软件的开发者,进程安全的考虑需要更加深入。本章主要针对线程和进程开发过程中的安全问题进行讲述,首先基于面向对象语言,讲解线程的的基本机制,然后讲解线程操作过程中的几个重要的安全问题:线程同步安全、线程协作安全、线程死锁、线程控制,最后讲解进程安全。3.1线程机制3.1.1为什么需要线程由于Java在线程操作方面具有较好的面向对象特性,也具有一定的代表性本章基于Java语言进行讲解。实际上,多线程最直观的说法是:让应用程序看起来好像同时能做好几件事情。为了表达这个问题,我们用一个案例来说明。比如,需要在控制台上每隔1秒钟打印一个欢迎信息。代码如下所示:

publicclassP03_01{publicstaticvoidmain(String[]args){while(true){System.out.println("Welcome");try{Thread.sleep(1000);}catch(Exceptionex){}}System.out.println("其他工作");//代码行1}}该程序似乎没有什么问题,运行时,"Welcome"也能不断打印。但是,我们发现,打印函数中的while循环是个死循环,也就是说,这个死循环不运行完毕,程序将不能作其他事情。比如,程序中的代码行1永远也无法运行。这就给程序的功能形成了巨大的阻碍。在实际应用开发的过程中,经常会出现一个程序看起来同时作好几件事情的情况,如程序进行一个用时较长的计算,希望该计算进行的时候,程序还可以做其他事情;程序进行一个用时较长的计算,希望该计算进行的时候,程序还可以做其他事情;软件要能够接受多个客户的请求,而让客户感觉不出等待;媒体播放器在播放歌曲的同时也能下载电影;财务软件在后台进行财务汇总的同时还能接受终端的请求;等等。在这些情况下,多线程就能够起到巨大的作用。线程和进程的关系很紧密,进程和线程是两个不同的概念,但是进程的范围大于线程。通俗地说,进程就是一个程序,线程是这个程序能够同时做的各件事情。比如,媒体播放机运行时就是一个进程,而媒体播放机同时做的下载文件和播放歌曲,就是两个线程。以上代码如果用线程来进行开发,在Java语言里面,就可以用如P03_02.java的方式(其他语言类似)。运行,就会发现,此时“打印欢迎信息”和“其他工作”就“同时”做了。3.1.2线程机制和生命周期每个程序至少自动拥有一个线程,称为主线程。当程序加载到内存时,启动主线程。从上节的程序可以看出,代码行:实际上相当于实例化一个新的线程对象,并运行该线程中的run()函数。该线程的运行并不影响主线程向下执行,这是为什么呢?这是由于多线程的机制实际上相当于CPU交替分配给不同的代码段来运行:也就是说,某一个时间片,某线程运行,下一个时间片,另一个线程运行,各个线程都有抢占CPU的权利,至于决定哪个线程抢占,是操作系统需要考虑的事情。由于时间片的轮转非常快,用户感觉不出各个线程抢占CPU的过程,看起来好像计算机在“同时”做好几件事情。WelcomeThreadwt=newWelcomeThread();wt.start(); 一个线程有从创建、运行到消亡的过程,称为线程的生命周期。用线程的状态(state)表明线程处在生命周期的哪个阶段。线程有创建、可运行、运行中、阻塞、死亡五种状态。通过线程的控制与调度可使线程在这几种状态间转化。这五种状态详细描述如下:1:创建状态:使用new运算符创建一个线程后。该线程仅仅是一个空对象,系统没有分配资源。2:可运行状态:使用start()方法启动一个线程后,系统分配了资源,使该线程处于可运行状态(Runnable)。3:运行中状态:占有CPU,执行线程的run()方法。4:阻塞状态:运行的线程因某种原因停止继续运行。5:死亡状态:线程结束。线程程的的安安全全隐隐患患可可能能出出现现在在各各个个状状态态。。一一般般说说来来,,线线程程的的安安全全性性来来源源于于两两个个方方面面::1:多多个个线线程程之之间间可可能能会会共共享享进进程程的的内内存存资资源源。。2:CPU的某某个个时时间间片片分分配配给给哪哪个个线线程程使使用用,,默默认认情情况况下下无无法法由由用用户户控控制制。。多线线程程的的安安全全问问题题比比较较复复杂杂,,解解决决方方法法繁繁多多,,在在这这里里我我们们阐阐述述几几个个比比较较典典型型的的安安全全问问题题。。3.2线程程同同步步安安全全3.2.1线程程同同步步默认认情情况况下下,,线线程程都都是是独独立立的的,,而而且且异异步步执执行行,,线线程程中中包包含含了了运运行行时时所所需需要要的的数数据据或或方方法法,,而而不不需需要要外外部部的的资资源源或或方方法法,,也也不不必必关关心心其其它它线线程程的的状状态态或或行行为为。。但但是是在在多多个个线线程程在在运运行行时时共共享享数数据据的的情情况况下下,,就就需需考考虑虑其其他他线线程程的的状状态态和和行行为为,,否否则则就就不不能能保保证证程程序序的的运运行行结结果果的的正正确确性性。。在在某某些些项项目目中中,,经经常常会会出出现现线线程程同同步步的的问问题题,,即即::多多个个线线程程在在访访问问同同一一资资源源时时,,会会出出现现安安全全问问题题。。本本节节基基于于一一个个简简单单的的案案例例,,针针对对线线程程的的同同步步问问题题进进行行阐阐述述。。所谓谓同同步步,,就就是是在在发发出出一一个个功功能能调调用用时时,,在在没没有有得得到到结结果果之之前前,,该该调调用用就就不不返返回回,,同同时时其其它它线线程程也也不不能能调调用用这这个个方方法法。。通通俗俗地地讲讲,,一一个个线线程程是是否否能能够够抢抢占占CPU,必必须须考考虑虑另另一一个个线线程程中中的的某某种种条条件件,,而而不不能能随随便便让让操操作作系系统统按按照照默默认认方方式式分分配配CPU,如如果果条条件件不不具具备备,,就就应应该该等等待待另另一一个个线线程程运运行行,,直直到到条条件件具具备备。。3.2.2案例例分分析析给出出一一个个案案例例::有有若若干干张张飞飞机机票票,,2个线线程程去去卖卖它它们们,,要要求求没没有有票票时时能能够够提提示示::没没有有票票了了。。以以最最后后剩剩下下3张票票为为例例。。首首先先用用传传统统方方法法来来编编写写这这段段代代码码。。代码码如如P03_03.java所示示。。运行行,,控控制制台台打打印印如如下下::这段段程程序序貌貌似似没没有有问问题题。。但但是是它它是是很很不不安安全全的的,,并并且且这这种种不不安安全全性性很很难难发发现现,,会会给给项项目目后后期期维维护护带带来来巨巨大大的的代代价价。。观察察程程序序中中的的代代码码行行1处的的注注释释,,当当只只剩剩下下一一张张票票时时,,线线程程1卖出了了最后后一张张票,,接着着要运运行ticketNum--,但在在ticketNum--还没来来得及及运行行的时时候,,线程程2有可能能抢占占CPU,来判判断当当前有有无票票可卖卖,此此时,,由于于线程程1还没有有将ticketNum--,当然然票数数还是是1,线程程2判断还还可以以买票票,这这样,,最后后一张张票卖卖出了了两次次。当当然,,上面面的程程序中中,没没有给给线程程2以买票票的机机会,,实际际上票票都由由线程程1卖出,,我们们看不不出其其中的的问题题。为为了让让大家家看清清这个个问题题,我我们模模拟线线程1和线程程2交替卖卖票的的情况况。将P03_03.java的代码码改为为P03_04.java:该代码码中,,增加加了一一行::程序序休眠眠1000毫秒,,让另另一个个线程程来抢抢占CPU。运行行,控控制台台打印印如下下:最后一一张票票被卖卖出两两次,,系统统不可可靠。。更为严严重的的是,,该问问题的的出现现很具具有随随机性性。比比如,,有些些项目目在实实验室室运行行阶段段没有有问题题,因因为哪哪个线线程抢抢占CPU,是由由操作作系统统决定定的,,用户户并没没有权权利干干涉,,也无无法预预测,,所以以,项项目可可能在在商业业运行行阶段段出现现了问问题,,等到到维护护人员员去查查问题题的时时候,,由于于问题题出现现的随随机性性,问问题可可能就就不出出现了了。这这种工工作往往往给给维护护带来来了巨巨大的的代价价。以上案案例是是多个个线程程消费费有限限资源源的情情况,,该情情况下下还有有很多多其他他案例例,如如:多多个线线程,,向有有限空空间写写数据据时::线程1写完数数据,,空间间满了了,但但没来来得及及告诉诉系统统;此时另另一个个线程程抢占占CPU,也来来写,,不知知道空空间已已满,,造成成溢出出。3.2.3解决方方案怎样解解决这这个问问题??很简简单,,就是是让一一个线线程卖卖票时时其他他线程程不能能抢占占CPU。根据据定义义,实实际上上相当当于要要实现现线程程的同同步,,通俗俗地讲讲,可可以给给共享享资源源(在在本例例中为为票))加一一把锁锁,这这把锁锁只有有一把把钥匙匙。哪哪个线线程获获取了了这把把钥匙匙,才才有权权利访访问该该共享享资源源。有一种种比较较直观观的方方法,,可以以在共共享资资源((如““票””)每每一个个对象象内部部都增增加一一个新新成员员,标标识““票””是否否正在在被卖卖中,,其他他线程程访问问时,,必须须检查查这个个标识识,如如果这这个标标识确确定票票正在在被卖卖中,,线程程不能能抢占占CPU。这种种设计计理论论上当当然也也是可可行,,但由由于线线程同同步的的情况况并不不是很很普遍遍,仅仅仅为为了这这种小小概率率事件件,在在所有有对象象内部部都开开辟另另一个个成员员空间间,带带来极极大的的空间间浪费费,增增加了了编程程难度度,所所以,,一般般不采采用这这种方方法。。现代代的编编程语语言的的设计计思路路都是是把同同步标标识加加在代代码段段上,,确切切的说说,是是把同同步标标识放放在““访访问共共享资资源((如卖卖票))的代代码段段”上上。不同语言中中,同步代代码段的实实现模型类类似,只是是表达方式式有些不同同。这里以以Java语言为例,,在Java语言中,synchronized关键字可以以解决这个个问题,整整个语法形形式表现为为:注意,synchronized后的“同步步锁对象””,必须是是可以被各各个线程共共享的,如如this、某个全局局标量等。。不能是一一个局部变变量。其原理为::当某一线线程运行同同步代码段段时,在““同步锁对对象”上置置一标记,,运行完这这段代码,,标记消除除。其他线线程要想抢抢占CPU运行这段代代码,必须须在“同步步锁对象””上先检查查该标记,,只有标记记处于消除除状态,才才能抢占CPU。在上面的的例子中,,this是一个“同同步锁对象象”。synchronized(同步锁对象象){//访问共享资资源,需要要同步的代代码段}因此,在上上面的案例例中,可以以将将卖票票的代码用用synchronized代码块包围围起来,““同步锁对对象”取this。如代码P03_05.java所示。运行,可以以得到如下下效果。这说明程序序运行完全全正常。从以上代码码可以看出出,该方法法的本质是是将需要独独占CPU的代码用synchronized(this)包围起来。。如前所述述,一个线线程进入这这段代码之之后,就在在this上加了一个个标记,直直到该线程程将这段代代码运行完完毕,才释释放这个标标记。如果果其他线程程想要抢占占CPU,先要检查查this上是否有这这个标记。。若有,就就必须等待待。但是可以看看出,该代代码实际上上运行较慢慢,因为一一个线程的的运行,必必须等待另另一个线程程将同步代代码段运行行完毕。因因此,从性性能上讲,,线程同步步是非常耗耗费资源的的一种操作作。我们要要尽量控制制线程同步步的代码段段范围,理理论上说,,同步的代代码段范围围越小,段段数越少越越好,因此此在某些情情况下,推推荐将小的的同步代码码段合并为为大的同步步代码段。。实际上,在在Java内,还可以以直接把synchronized关键字直接接加在函数数的定义上上,这也是是一种可以以推荐的方方法。不过,值得得一提的是是,如果不不能确定整整个函数都都需要同步步,那就要要尽量避免免直接把synchronized加在函数定定义上的做做法。如前前所述,要要控制同步步粒度,同同步的代码码段越小越越好,synchronized控制的范围围越小越好好,否则造造成不必要要的系统开开销。所以以,在实际际开发的过过程中,要要十分小心心,因为过过多的线程程等待可能能造成系统统性能的下下降,甚至至造成死锁锁。3.3线程协作安安全3.3.1线程协协作有些情况下下,多个线线程合作完成一件事事情的几个个步骤,此此时线程之之间实现了了协作。如如一个工作作需要若干干个步骤,,各个步骤骤都比较耗耗时,不能能因为它们们的运行,,影响程序序的运行效效果,最好好的方法就就是将各步步用线程实实现。但是是,由于线线程随时都都有可能抢抢占CPU,可能在前前面一个步步骤没有完完成时,后后面的步骤骤线程就已已经运行,,该安全隐隐患造成系系统得不到到正确结果果。3.3.2案例分析给出一个案案例:线程程1负责完成一一个复杂运运算(比较较耗时),,线程2负责得到结结果,并将将结果进行行下一步处处理。如::某个科学学计算系统统中,线程程1负责计算1-1000各个数字的的和(暂且认为它它非常耗时时),线程2负责得到这这个结果并并且写入数数据库。读者首先想想到的是将将耗时的计计算放入线线程。这是是正确的想想法。首先先用传统线线程方法来来编写这段段代码,代代码如P03_06.java所示。该程序貌似似没有问题题,也能够够打印正确确结果,但但是和上一一节的例子子一样,它它也是很不不安全的,,这种不安安全性也很很难发现,,也会给项项目后期维维护带来巨巨大的代价价。该程序序的安全隐隐患在哪里里呢?观察cal()函数中的代代码,当线线程th1运行后,线线程th2运行,此时时,线程th2随时可能抢抢占CPU,而不一定定要等线程程th1运行完毕。。当然,在在上面的例例子中,可可能因为线线程th1运行较快,,th2在它运行的的过程中没没有抢占CPU,“碰巧””得到了正正确结果,,但是如果果让线程th2抢占CPU,这样,系系统可能得得不到正确确结果。为为了解释这这个问题,,将P03_06.java的代码改为为P03_07.java该代码中,,增加了一一行:程序序休眠1毫秒,让另另一个线程程来抢占CPU。运行,控控制台打印印如下:很显然,这这个结果不不是我们所所需要的。。那为什么sum得到的结果果为1呢?很明显显,线程th1的start函数运行时时,相当于于让求和过过程以多线线程形式运运行,在它它“休眠””之际,th2就抢占了CPU,在求和还还没开始做做或只完成成一部分时时就打印sum,导致得到到不正常结结果。3.3.3解决方案怎样解决??显而易见见,方法是是:在运行行一个线程程时,命令令其他线程程等待该线线程运行完完毕,才能能抢占CPU进行运行。。对于该问问题,不同同语言解决决方法类似似。以Java语言为例,,在Java语言中,线线程的join()方法可以解解决这个问问题。见代码P03_08.java运行正常。。实际上,,该程序相相当于摒弃弃了“线程程就是为了了程序看起起来同时做做好几件事事情”的思思想,将并并发程序又又变成了顺顺序的,如如果线程th1没有运行完完毕的话,,程序会在在th.join()处堵塞。如如果cal()函数耗时较较长,程序序将一直等等待。一般般的方法是是,可以将将该工作放放在另一个个线程中,,这样,既既不会堵塞塞主程序,,又能够保保证数据安安全性。见代码P03_09.java3.4线程死锁安安全3.4.1线程死死锁死锁(DeadLock),是指两个个或两个以以上的线程程在执行过过程中,因因争夺资源源而造成的的一种互相相等待的现现象。此时时称系统处处于死锁状状态,这些些永远在互互相等待的的线程称为为死锁线程程。产生死锁的的四个必要要条件是::互斥条件::资源每次次只能被一一个线程使使用。如前前面的“线线程同步代代码段”,,就是只能能被一个线线程使用的的典型资源源;请求与保持持条件:一一个线程请请求资源,,但因为某某种原因,,该资源无无法分配给给它,于是是该线程阻阻塞,此时时,它对已已获得的资资源保持不不放;不剥夺条件件:进程已已获得的资资源,在未未使用完之之前,不管管其是否阻阻塞,无法法强行剥夺夺;循环等待条条件:若干干进程之间间互相等待待,形成一一种头尾相相接的循环环等待资源源关系。这四个条件件是死锁的的必要条件件,只要系系统发生死死锁,这些些条件必然然成立,而而只要上述述条件之一一不满足,,就不会发发生死锁。。3.4.2案例分析以Java语言为例,,死锁一般般来源于代代码段的同同步,当一一段同步代代码被某线线程运行时时,其他线线程可能进进入堵塞状状态(无法抢占CPU),而刚好在在该线程中中,访问了了某个对象象,此时,,除非同步步锁定被解解除,否则则其他线程程就不能访访问那个对对象。这可可以称为““线程正在在等待一个个对象资源源”。如果果出现一种种极端情况况,一个线线程等候另另一个对象象,而另一一个对象又又在等候下下一个对象象,以此类类推。这个个“等候候链”如果果进入封闭闭状态,也也就是说,,最后那个个对象等候候的是第一一个对象,,此时,所所有线程都都会陷入无无休止的相相互等待状状态,造成成死锁。尽尽管这种情情况并非经经常出现,,但一旦碰碰到,程序序的调试将将变得异常常艰难。在这里给出一一个死锁的案案例,如代码码P03_10.java这段程序也貌貌似没有问题题。但是和上上一节的例子子一样,它也也是很不安全全的,这种不不安全性也很很难发现。观察run()函数中的代码码,当th1运行后,进入入代码段1,锁定了S1,如果此时th2运行,抢占CPU,进入代码段段3,锁定S2,那么th1就无法运行代代码段2,但是又没有有释放S1,此时,th2也就不能运行行代码段4。造成互相等等待。为了模模拟这个过程程,我们在程程序中增加让让其休眠的代代码,好让另另一个线程来来抢占CPU。将P03_10.java的代码改为P03_11.java该代码中,增增加了一行::程序休眠1000毫秒,让另一一个线程来抢抢占CPU。运行,控制制台打印如下下:两个线程陷入入无休止的等等待。其原因因是,线程th1进入代码段1后,线程2抢占CPU,锁定了S2,而线程th1对S1的锁定又没有有解除,造成成线程th2无法运行下去去,当然,由由于线程th2锁定了S2,线程th1也无法运行下下去。死锁是一个很很重要的问题题,它能导致致整个应用程程序慢慢终止止,尤其是当当开发人员不不熟悉如何分分析死锁环境境的时候,还还很难被分离离和修复。3.4.3解决方案就语言本身来来说,尚未直直接提供防止止死锁的帮助助措施,需要要我们通过谨谨慎的设计来来避免。一般般情况下,我我们主要是针针对死锁产生生的四个必要要条件来进行行破坏,用以以避免和预防防死锁。在系系统设计、线线程开发等方方面,注意如如何不让这四四个必要条件件成立,如何何确定资源的的合理分配算算法,避免线线程永久占据据系统资源。。以Java为例,Java并不提供对死死锁的检测机机制。但可以以通过javathreaddump来进行判断::一般情况下下,当死锁发发生时,Java虚拟机处于挂挂起状态,threaddump可以给出静态态稳定的信息息,从操作系系统上观察,,虚拟机的CPU占用率为零,,这时可以收收集threaddump,查找"waitingformonitorentry"的线程,如果果大量thread都在等待给同同一个地址上上锁,说明很很可能死锁发发生了。解决死锁没有有简单的方法法,这是因为为线程产生死死锁都各有各各的原因,而而且往往具有有很高的负载载。从技术上上讲,可以用用如下方法来来进行死锁排排除:可以撤消陷于于死锁的全部部线程。可以逐个撤消消陷于死锁的的进程,直到到死锁不存在在。从陷于死锁的的线程中逐个个强迫放弃所所占用的资源源,直至死锁锁消失。提示:关于死锁的检检测与解除,,有很多重要要算法,如资资源分配算法法、银行家算算法等。在操操作系统的一一些参考资料料中应该可以以进行足够了了解。很多软件产品品内置了死锁锁解决策略,,可做参考。。如:数据库死锁。。一个连接占占用了另一个个连接所需的的数据库锁,,它可能阻塞塞另一个连接接。如果两个个或两个以上上的连接相互互阻塞,产生生死锁。该情情况下,一般般会强制销毁毁一个连接((通常是使用用最少的连接接),并回滚滚其事务。这这将释放所有有与已经结束束的事务相关关联的锁,至至少允许其他他连接中有一一个可以获取取它们正在被被阻塞的锁。。资源池耗尽死死锁。资源池池太小,而每每个线程需要要的资源超过过了池中的可可用资源,产产生死锁。此此时可以增加加连接池的大大小或者重构构代码,以便便单个线程不不需要同时使使用很多资源源。3.5线程程控控制制安安全全3.5.1安全全隐隐患患线程程控控制制主主要要是是对对线线程程生生命命周周期期的的一一些些操操作作,,如如暂暂停停、、继继续续、、消消亡亡等等。。本本节节以以Java语言言为为例例,,讲讲解解线线程程控控制制中中的的一一些些安安全全问问题题。。Java中提提供供了了对对线线程程生生命命周周期期进进行行控控制制的的函函数数::stop():停停止止线线程程;;suspend():暂暂停停线线程程的的运运行行;;resume():继继续续线线程程的的运运行行::destroy():让让线线程程销销毁毁;;等等等等。。线程程生生命命周周期期中中的的安安全全问问题题主主要要体体现现在在::线程程暂暂停停或或者者终终止止时时,,可可能能对对某某些些资资源源的的锁锁并并没没有有释释放放,,它它所所保保持持的的任任何何资资源源都都会会保保持持锁锁定定状状态态;;线程程暂暂停停之之后后,,我我们们无无法法预预计计它它什什么么时时候候会会继继续续(一般般和和用用户户操操作作有有关关),如如果果对对某某个个资资源源的的锁锁长长期期被被保保持持,,其其他他线线程程在在任任何何时时候候都都无无法法再再次次访访问问该该资资源源,,极极有有可可能能造造成成死死锁锁。。针对对这这个个问问题题,,为为减减少少出出现现死死锁锁的的可可能能,,Java1.2中,,将将Thread的stop(),suspend(),resume()以及及destroy()方法法定定义义为为““已已过过时时””方方法法,,不不再再推推荐荐使使用用。。3.5.2案例例分分析析如前前所所述述,,线线程程的的暂暂停停和和继继续续,,早早期期采采用用suspend()和resume()方法法,,但但是是容容易易发发生生死死锁锁。。以以线线程程暂暂停停为为例例,,调调用用suspend()的时时候候,,目目标标线线程程会会停停下下来来,,但但却却仍仍然然持持有有在在这这之之前前获获得得的的锁锁定定。。此此时时,,其其他他任任何何线线程程都都不不能能访访问问锁锁定定的的资资源源,,除除非非被被““挂挂起起””的的线线程程恢恢复复运运行行。。如如果果它它们们想想恢恢复复目目标标线线程程,,同同时时又又试试图图使使用用任任何何一一个个锁锁定定的的资资源源,,就就会会造造成成死死锁锁。。下面面给给出出一一个个案案例例,,来来说说明明这这个个问问题题。。屏屏幕幕上上不不断断打打印印欢欢迎迎信信息息,,点点击击按按钮钮,,打打印印工工作作暂暂停停;;再再点点击击,,继继续续打打印印。。传统统代代码码如如P03_12.java如果果点点击击““暂暂停停””按按钮钮,,则则暂暂停停打打印印;;再再点点击击,,继继续续打打印印。。如上上所所述述,,该该代代码码实实际际上上在在事事件件响响应应中中用用suspend()和resume()来控控制制线线程程的的暂暂停停和和继继续续,,是是不不安安全全的的。。3.5.3解决决方方案案解决决该该问问题题,,常常见见的的方方法法有有如如下下几几种种::1:当当需需要要暂暂停停时时,,干干脆脆让让线线程程的的run()方法法结结束束运运行行以以释释放放资资源源(实际际上上就就是是让让该该线线程程永永久久结结束束);继继续续时时,,新新开开辟辟一一个个线线程程继继续续工工作作。。怎怎样样让让run()方法法结结束束呢呢??一一般般可可用用一一个个标标志志告告诉诉线线程程什什么么时时候候通通过过退退出出自自己己的的run()方法法来来中中止止自自己己的的执执行行。。2:将将线线程程暂暂停停或或继继续续,,不不使使用用suspend()和resume(),可可在在Thread类中中置置入入一一个个标标志志,,指指出出线线程程应应该该活活动动还还是是挂挂起起。。若若标标志志指指出出线线程程应应该该挂挂起起,,便便用用wait()命其其进进入入等等待待状状态态。。若若标标志志指指出出线线程程应应当当恢恢复复,,则则用用一一个个notify()重新启动线线程。3:不推荐使使用stop()来终止阻塞塞的线程,,而应换用用由Thread提供的interrupt()方法,以便便中止并退退出堵塞的的代码。3.6进程安全全3.6.1进程概述述进程是一一个执行行中的程程序,对对每一个个进程来来说,都都有自己己独立的的一片内内存空间间和一组组系统资资源。进进程由进进程控制制块、程程序段、、数据段段三部分分组成。。在进程程概念中中,每一一个进程程的内部部数据和和状态都都是完全全独立的的。一个进程程可以包包含若干干线程,,线程可可以帮助助应用程程序同时时做几件件事(比如一个个线程向向磁盘写写入文件件,另一一个则接接收用户户的按键键操作并并及时做做出反应应,互相相不干扰扰)。进程也也有运行行、阻塞塞、就绪绪三种状状态,并并随一定定条件而而相互转转化。3.6.2进程安全全问题由于进程程的独立立性,从从应用的的角度讲讲,进程程安全比比线程安安全更受受重视,,一般针针对已有有的进程程进行安安全方面面的控制制。如::在系统安安全中发发现并清清除病毒毒进程;;在网络应应用中,,优化守守护进程程或端口口扫描进进程;等等等。不过,从从开发者者(编程程)的角角度,进进程的安安全所需需要考虑虑的问题题和线程程类似,,但由于于线程能能够共享享进程的的资源,,所以线线程安全全一般考考虑的问问题比进进程安全全多。不不过,对对于开发发多个进进程能够够运行的的系统软软件(如如操作系系统),,进程的的安全就就应该重重点考虑虑了。一一般情况况下,此此时考虑虑的问题题和线程程安全类类似,因因为在这这种软件件中,各各个进程程在使用用系统有有限的资资源,和和线程安安全中考考虑的问问题类似似,在此此不再叙叙述。小结本章主要要针对线线程和进进程开发发过程中中的安全全问题进进行讲述述。从开开发者角角度,首首先讲解解了线程程的的基基本机制制,然后后讲解线线程操作作过程中中几个重重要的安安全问题题:线程程同步安安全、线线程协作作安全、、线程死死锁、线线程控制制安全等等。最后后讲解了了进程安安全。练习1:将P03_05.java中的同步步代码写写在一个个同步函函数中。。2:线程1首先用Pen写字,然然后用Pencil写字;线线程2首先用Pencil写字,然然后用Pen写字;编编写一个个因为线线程1等待Pencil,线程2等待Pen而造成死死锁的例例子,并并提出解解决方法法。3:两个线线程,向向空间有有限的数数组中写写数据。。写一段段代码,,具有数数组溢出出的安全全隐患,,并提出出解决方方案。4:界面上上有个小小红球,,要求能能够慢慢慢掉下来来然后弹弹起来;;为了逼逼真,当当球在比比较上方方的时候候,球比比较大,,球落下下时,慢慢慢变小小;在界界面右下下角有一一个“暂暂停”按按钮,可可以让动动画暂停停;动画画暂停之之后又可可以点击击按钮让让动画继继续运行行。5:举例说说明进程程安全和和线程安安全问题题所考虑虑的问题题的不同同之处??6:Oracle数据库中中,多个个用户访访问同一一数据,,可能会会造成死死锁,请请你设计计一个案案例,进进行测试试。并观观察其解解决方法法。7:很多语语言中提提供了定定时器(Timer),让某个个功能定定时执行行,该功功能也可可以用线线程实现现,比较较两种方方法的优优劣。8:编写一一个程序序,每隔隔一秒,,界面上上方落下下来一个个字母。。字母落落到界面面底端,,消失,,这里怎怎样控制制线程的的开始和和结束??9:飞机射射击游戏戏中线程程是怎样样应用的的?10:将P03_11.java代码中同同步段改改为同步步方法。。9、静静夜夜四四无无邻邻,,荒荒居居旧旧业业贫贫。。。。12月月-2212月月-22Tuesday,December20,202210、雨中中黄叶叶树,,灯下下白头头人。。。03:30:2603:30:2603:3012/20/20223:30:26AM11、以我我独沈沈久,,愧君君相见见频。。。12月月-2203:30:2603:30Dec-2220-Dec-2212、故人江海别别,几度隔山山川。。03:30:2703:30:2703:30Tuesday,December20,202213、乍见翻疑梦梦,相悲各问问年。。12月-2

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论