03講_線程進(jìn)程安全ppt課件_第1頁
03講_線程進(jìn)程安全ppt課件_第2頁
03講_線程進(jìn)程安全ppt課件_第3頁
03講_線程進(jìn)程安全ppt課件_第4頁
03講_線程進(jìn)程安全ppt課件_第5頁
已閱讀5頁,還剩39頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、第三章線程/進(jìn)程平安進(jìn)程和線程是兩個范圍不同的概念。進(jìn)程是程序在計算機(jī)上的一次執(zhí)行活動。運(yùn)轉(zhuǎn)一個程序,相當(dāng)于啟動了一個進(jìn)程。進(jìn)程是操作系統(tǒng)進(jìn)展資源分配的單位,通俗地講,是一個正在執(zhí)行的程序。線程是進(jìn)程中的一個實(shí)體,是被系統(tǒng)獨(dú)立調(diào)度和分派的根本單位,它可與同屬一個進(jìn)程的其它線程共享進(jìn)程所擁有的全部資源。一個線程可以創(chuàng)建和吊銷另一個線程,同一進(jìn)程中的多個線程之間可以并發(fā)執(zhí)行。比如,一個在線播放軟件,在播放歌曲的同時還可以進(jìn)展下載,就可以為這兩件任務(wù)由不同的線程完成。線程和進(jìn)程的開發(fā)和相關(guān)操作,在程序設(shè)計中具有重要位置,線程和進(jìn)程的平安和系統(tǒng)的平安息息相關(guān)。對于不夠熟練的程序員來說,很容易出現(xiàn)平安隱

2、患,而這些平安問題又具有不延續(xù)發(fā)生,難于調(diào)試等特點(diǎn)。普通說來,線程的平安性主要來源于其運(yùn)轉(zhuǎn)的并發(fā)性和對資源的共享性;進(jìn)程的平安性主要在運(yùn)用級別,在于其對系統(tǒng)的要挾性,不過對于系統(tǒng)軟件的開發(fā)者,進(jìn)程平安的思索需求更加深化。本章主要針對線程和進(jìn)程開發(fā)過程中的平安問題進(jìn)展講述,首先基于面向?qū)ο笱哉Z,講解線程的的根本機(jī)制,然后講解線程操作過程中的幾個重要的平安問題:線程同步平安、線程協(xié)作平安、線程死鎖、線程控制,最后講解進(jìn)程平安。3.1 線程機(jī)制3.1.1 為什么需求線程由于Java在線程操作方面具有較好的面向?qū)ο筇匦?,也具有一定的代表性本章基于Java言語進(jìn)展講解。實(shí)踐上,多線程最直觀的說法是:讓運(yùn)

3、用程序看起來好似同時能做好幾件事情。為了表達(dá)這個問題,我們用一個案例來闡明。比如,需求在控制臺上每隔1秒鐘打印一個歡迎信息。代碼如下所示: public class P03_01 public static void main(String args) while(true) System.out.println(Welcome); try Thread.sleep(1000); catch(Exception ex) System.out.println(其他任務(wù)); /代碼行1 該程序似乎沒有什么問題,運(yùn)轉(zhuǎn)時,Welcome也能不斷打印。但是,我們發(fā)現(xiàn),打印函數(shù)中的while循環(huán)是個死循環(huán)

4、,也就是說,這個死循環(huán)不運(yùn)轉(zhuǎn)終了,程序?qū)⒉荒茏髌渌虑?。比如,程序中的代碼行1永遠(yuǎn)也無法運(yùn)轉(zhuǎn)。這就給程序的功能構(gòu)成了宏大的妨礙。在實(shí)踐運(yùn)用開發(fā)的過程中,經(jīng)常會出現(xiàn)一個程序看起來同時作好幾件事情的情況,如 程序進(jìn)展一個用時較長的計算,希望該計算進(jìn)展的時候,程序還可以做其他事情;程序進(jìn)展一個用時較長的計算,希望該計算進(jìn)展的時候,程序還可以做其他事情; 軟件要可以接受多個客戶的懇求,而讓客戶覺得不出等待; 媒體播放器在播放歌曲的同時也能下載電影; 財務(wù)軟件在后臺進(jìn)展財務(wù)匯總的同時還能接受終端的懇求;等等。 在這些情況下,多線程就可以起到宏大的作用。線程和進(jìn)程的關(guān)系很嚴(yán)密,進(jìn)程和線程是兩個不同的概念,

5、但是進(jìn)程的范圍大于線程。通俗地說,進(jìn)程就是一個程序,線程是這個程序可以同時做的各件事情。比如,媒體播放機(jī)運(yùn)轉(zhuǎn)時就是一個進(jìn)程,而媒體播放機(jī)同時做的下載文件和播放歌曲,就是兩個線程。以上代碼假設(shè)用線程來進(jìn)展開發(fā),在Java言語里面,就可以用如P03_02.java的方式(其他言語類似) 。運(yùn)轉(zhuǎn),就會發(fā)現(xiàn),此時“打印歡迎信息和“其他任務(wù)就“同時做了。3.1.2 線程機(jī)制和生命周期每個程序至少自動擁有一個線程,稱為主線程。當(dāng)程序加載到內(nèi)存時,啟動主線程。從上節(jié)的程序可以看出,代碼行:實(shí)踐上相當(dāng)于實(shí)例化一個新的線程對象,并運(yùn)轉(zhuǎn)該線程中的run()函數(shù)。該線程的運(yùn)轉(zhuǎn)并不影響主線程向下執(zhí)行,這是為什么呢?這

6、是由于多線程的機(jī)制實(shí)踐上相當(dāng)于CPU交替分配給不同的代碼段來運(yùn)轉(zhuǎn):也就是說,某一個時間片,某線程運(yùn)轉(zhuǎn),下一個時間片,另一個線程運(yùn)轉(zhuǎn),各個線程都有搶占CPU的權(quán)益,至于決議哪個線程搶占,是操作系統(tǒng)需求思索的事情。由于時間片的輪轉(zhuǎn)非???,用戶覺得不出各個線程搶占CPU的過程,看起來好似計算機(jī)在“同時做好幾件事情。WelcomeThread wt = new WelcomeThread(); wt.start(); 一個線程有從創(chuàng)建、運(yùn)轉(zhuǎn)到消亡的過程,稱為線程的生命周期。用線程的形狀state闡明線程處在生命周期的哪個階段。線程有創(chuàng)建、可運(yùn)轉(zhuǎn)、運(yùn)轉(zhuǎn)中、阻塞、死亡五種形狀。經(jīng)過線程的控制與調(diào)度可使線程

7、在這幾種形狀間轉(zhuǎn)化。這五種形狀詳細(xì)描畫如下:1:創(chuàng)建形狀:運(yùn)用new運(yùn)算符創(chuàng)建一個線程后。該線程僅僅是一個空對象,系統(tǒng)沒有分配資源。2:可運(yùn)轉(zhuǎn)形狀:運(yùn)用start()方法啟動一個線程后,系統(tǒng)分配了資源,使該線程處于可運(yùn)轉(zhuǎn)形狀Runnable。3:運(yùn)轉(zhuǎn)中形狀:占有CPU,執(zhí)行線程的run()方法。4:阻塞形狀:運(yùn)轉(zhuǎn)的線程因某種緣由停頓繼續(xù)運(yùn)轉(zhuǎn)。5:死亡形狀:線程終了。 線程的平安隱患能夠出如今各個形狀。普通說來,線程的平安性來源于兩個方面:1:多個線程之間能夠會共享進(jìn)程的內(nèi)存資源。2:CPU的某個時間片分配給哪個線程運(yùn)用,默許情況下無法由用戶控制。多線程的平安問題比較復(fù)雜,處理方法繁多,在這里我

8、們論述幾個比較典型的平安問題。 3.2 線程同步平安3.2.1 線程同步默許情況下,線程都是獨(dú)立的,而且異步執(zhí)行,線程中包含了運(yùn)轉(zhuǎn)時所需求的數(shù)據(jù)或方法,而不需求外部的資源或方法,也不用關(guān)懷其它線程的形狀或行為。但是在多個線程在運(yùn)轉(zhuǎn)時共享數(shù)據(jù)的情況下,就需思索其他線程的形狀和行為,否那么就不能保證程序的運(yùn)轉(zhuǎn)結(jié)果的正確性。在某些工程中,經(jīng)常會出現(xiàn)線程同步的問題,即:多個線程在訪問同一資源時,會出現(xiàn)平安問題。本節(jié)基于一個簡單的案例,針對線程的同步問題進(jìn)展論述。所謂同步,就是在發(fā)出一個功能調(diào)用時,在沒有得到結(jié)果之前,該調(diào)用就不前往,同時其它線程也不能調(diào)用這個方法。通俗地講,一個線程能否可以搶占CPU,

9、必需思索另一個線程中的某種條件,而不能隨意讓操作系統(tǒng)按照默許方式分配CPU,假設(shè)條件不具備,就應(yīng)該等待另一個線程運(yùn)轉(zhuǎn),直到條件具備。3.2.2 案例分析給出一個案例:有假設(shè)干張飛機(jī)票,2個線程去賣它們,要求沒有票時可以提示:沒有票了。以最后剩下3張票為例。首先用傳統(tǒng)方法來編寫這段代碼。代碼如P03_03.java所示。運(yùn)轉(zhuǎn),控制臺打印如下: 這段程序貌似沒有問題。但是它是很不平安的,并且這種不平安性很難發(fā)現(xiàn),會給工程后期維護(hù)帶來宏大的代價。察看程序中的代碼行1處的注釋,當(dāng)只剩下一張票時,線程1賣出了最后一張票,接著要運(yùn)轉(zhuǎn)ticketNum-,但在ticketNum-還沒來得及運(yùn)轉(zhuǎn)的時候,線程2

10、有能夠搶占CPU,來判別當(dāng)前有無票可賣,此時,由于線程1還沒有將ticketNum-,當(dāng)然票數(shù)還是1,線程2判別還可以買票,這樣,最后一張票賣出了兩次。當(dāng)然,上面的程序中,沒有給線程2以買票的時機(jī),實(shí)踐上票都由線程1賣出,我們看不出其中的問題。為了讓大家看清這個問題,我們模擬線程1和線程2交替賣票的情況。將P03_03.java的代碼改為P03_04.java:該代碼中,添加了一行:程序休眠1000毫秒,讓另一個線程來搶占CPU。運(yùn)轉(zhuǎn),控制臺打印如下: 最后一張票被賣出兩次,系統(tǒng)不可靠。更為嚴(yán)重的是,該問題的出現(xiàn)很具有隨機(jī)性。比如,有些工程在實(shí)驗(yàn)室運(yùn)轉(zhuǎn)階段沒有問題,由于哪個線程搶占CPU,是由

11、操作系統(tǒng)決議的,用戶并沒有權(quán)益干涉,也無法預(yù)測,所以,工程能夠在商業(yè)運(yùn)轉(zhuǎn)階段出現(xiàn)了問題,等到維護(hù)人員去查詢題的時候,由于問題出現(xiàn)的隨機(jī)性,問題能夠就不出現(xiàn)了。這種任務(wù)往往給維護(hù)帶來了宏大的代價。以上案例是多個線程消費(fèi)有限資源的情況,該情況下還有很多其他案例,如:多個線程,向有限空間寫數(shù)據(jù)時:線程1寫完數(shù)據(jù),空間滿了,但沒來得及通知系統(tǒng);此時另一個線程搶占CPU,也來寫,不知道空間已滿,呵斥溢出。3.2.3 處理方案怎樣處理這個問題?很簡單,就是讓一個線程賣票時其他線程不能搶占CPU。根據(jù)定義,實(shí)踐上相當(dāng)于要實(shí)現(xiàn)線程的同步,通俗地講,可以給共享資源在本例中為票加一把鎖,這把鎖只需一把鑰匙。哪個線

12、程獲取了這把鑰匙,才有權(quán)益訪問該共享資源。有一種比較直觀的方法,可以在共享資源如“票每一個對象內(nèi)部都添加一個新成員,標(biāo)識“票能否正在被賣中,其他線程訪問時,必需檢查這個標(biāo)識,假設(shè)這個標(biāo)識確定票正在被賣中,線程不能搶占CPU。這種設(shè)計實(shí)際上當(dāng)然也是可行,但由于線程同步的情況并不是很普遍,僅僅為了這種小概率事件,在一切對象內(nèi)部都開辟另一個成員空間,帶來極大的空間浪費(fèi),添加了編程難度,所以,普通不采用這種方法。現(xiàn)代的編程言語的設(shè)計思緒都是把同步標(biāo)識加在代碼段上,確切的說,是把同步標(biāo)識放在“ 訪問共享資源如賣票的代碼段上。不同言語中,同步代碼段的實(shí)現(xiàn)模型類似,只是表達(dá)方式有些不同。這里以Java言語為

13、例,在Java言語中,synchronized關(guān)鍵字可以處理這個問題,整個語法方式表現(xiàn)為: 留意,synchronized后的“同步鎖對象,必需是可以被各個線程共享的,如this、某個全局標(biāo)量等。不能是一個部分變量。其原理為:當(dāng)某一線程運(yùn)轉(zhuǎn)同步代碼段時,在“同步鎖對象上置一標(biāo)志,運(yùn)轉(zhuǎn)完這段代碼,標(biāo)志消除。其他線程要想搶占CPU運(yùn)轉(zhuǎn)這段代碼,必需在“同步鎖對象上先檢查該標(biāo)志,只需標(biāo)志處于消除形狀,才干搶占CPU。在上面的例子中,this是一個“同步鎖對象。 synchronized(同步鎖對象) / 訪問共享資源,需求同步的代碼段 因此,在上面的案例中,可以將將賣票的代碼用synchronize

14、d代碼塊包圍起來,“同步鎖對象取this。如代碼P03_05.java所示。運(yùn)轉(zhuǎn),可以得到如下效果。 這闡明程序運(yùn)轉(zhuǎn)完全正常。從以上代碼可以看出,該方法的本質(zhì)是將需求獨(dú)占CPU的代碼用synchronized(this)包圍起來。如前所述,一個線程進(jìn)入這段代碼之后,就在this上加了一個標(biāo)志,直到該線程將這段代碼運(yùn)轉(zhuǎn)終了,才釋放這個標(biāo)志。假設(shè)其他線程想要搶占CPU,先要檢查this上能否有這個標(biāo)志。假設(shè)有,就必需等待。但是可以看出,該代碼實(shí)踐上運(yùn)轉(zhuǎn)較慢,由于一個線程的運(yùn)轉(zhuǎn),必需等待另一個線程將同步代碼段運(yùn)轉(zhuǎn)終了。因此,從性能上講,線程同步是非常耗費(fèi)資源的一種操作。我們要盡量控制線程同步的代碼段

15、范圍,實(shí)際上說,同步的代碼段范圍越小,段數(shù)越少越好,因此在某些情況下,引薦將小的同步代碼段合并為大的同步代碼段。實(shí)踐上,在Java內(nèi),還可以直接把synchronized關(guān)鍵字直接加在函數(shù)的定義上,這也是一種可以引薦的方法。不過,值得一提的是,假設(shè)不能確定整個函數(shù)都需求同步,那就要盡量防止直接把synchronized加在函數(shù)定義上的做法。如前所述,要控制同步粒度,同步的代碼段越小越好,synchronized控制的范圍越小越好,否那么呵斥不用要的系統(tǒng)開銷。所以,在實(shí)踐開發(fā)的過程中,要非常小心,由于過多的線程等待能夠呵斥系統(tǒng)性能的下降,甚至呵斥死鎖。3.3 線程協(xié)作平安3.3.1 線程協(xié)作有些

16、情況下,多個線程協(xié)作完成一件事情的幾個步驟,此時線程之間實(shí)現(xiàn)了協(xié)作。如一個任務(wù)需求假設(shè)干個步驟,各個步驟都比較耗時,不能由于它們的運(yùn)轉(zhuǎn),影響程序的運(yùn)轉(zhuǎn)效果,最好的方法就是將各步用線程實(shí)現(xiàn)。但是,由于線程隨時都有能夠搶占CPU,能夠在前面一個步驟沒有完成時,后面的步驟線程就曾經(jīng)運(yùn)轉(zhuǎn),該平安隱患呵斥系統(tǒng)得不到正確結(jié)果。3.3.2 案例分析給出一個案例:線程1擔(dān)任完成一個復(fù)雜運(yùn)算比較耗時,線程2擔(dān)任得到結(jié)果,并將結(jié)果進(jìn)展下一步處置。如:某個科學(xué)計算系統(tǒng)中,線程1擔(dān)任計算1-1000各個數(shù)字的和(暫且以為它非常耗時),線程2擔(dān)任得到這個結(jié)果并且寫入數(shù)據(jù)庫。讀者首先想到的是將耗時的計算放入線程。這是正確

17、的想法。首先用傳統(tǒng)線程方法來編寫這段代碼,代碼如P03_06.java所示。該程序貌似沒有問題,也可以打印正確結(jié)果,但是和上一節(jié)的例子一樣,它也是很不平安的,這種不平安性也很難發(fā)現(xiàn),也會給工程后期維護(hù)帶來宏大的代價。該程序的平安隱患在哪里呢?察看cal()函數(shù)中的代碼,當(dāng)線程th1運(yùn)轉(zhuǎn)后,線程th2運(yùn)轉(zhuǎn),此時,線程th2隨時能夠搶占CPU,而不一定要等線程th1運(yùn)轉(zhuǎn)終了。當(dāng)然,在上面的例子中,能夠由于線程th1運(yùn)轉(zhuǎn)較快,th2在它運(yùn)轉(zhuǎn)的過程中沒有搶占CPU,“碰巧得到了正確結(jié)果,但是假設(shè)讓線程th2搶占CPU,這樣,系統(tǒng)能夠得不到正確結(jié)果。為了解釋這個問題,將P03_06.java的代碼改為P

18、03_07.java該代碼中,添加了一行:程序休眠1毫秒,讓另一個線程來搶占CPU。運(yùn)轉(zhuǎn),控制臺打印如下: 很顯然,這個結(jié)果不是我們所需求的。那為什么sum得到的結(jié)果為1呢?很明顯,線程th1的start函數(shù)運(yùn)轉(zhuǎn)時,相當(dāng)于讓求和過程以多線程方式運(yùn)轉(zhuǎn),在它“休眠之際,th2就搶占了CPU,在求和還沒開場做或只完成一部分時就打印sum,導(dǎo)致得到不正常結(jié)果。3.3.3 處理方案怎樣處理?顯而易見,方法是:在運(yùn)轉(zhuǎn)一個線程時,命令其他線程等待該線程運(yùn)轉(zhuǎn)終了,才干搶占CPU進(jìn)展運(yùn)轉(zhuǎn)。對于該問題,不同言語處理方法類似。以Java言語為例,在Java言語中,線程的join()方法可以處理這個問題。見代碼P03

19、_08.java運(yùn)轉(zhuǎn)正常。實(shí)踐上,該程序相當(dāng)于摒棄了“線程就是為了程序看起來同時做好幾件事情的思想,將并發(fā)程序又變成了順序的,假設(shè)線程th1沒有運(yùn)轉(zhuǎn)終了的話,程序會在th.join()處堵塞。假設(shè)cal()函數(shù)耗時較長,程序?qū)⒉粩嗟却?。普通的方法是,可以將該任?wù)放在另一個線程中,這樣,既不會堵塞主程序,又可以保證數(shù)據(jù)平安性。見代碼P03_09.java 3.4 線程死鎖平安3.4.1 線程死鎖死鎖(DeadLock),是指兩個或兩個以上的線程在執(zhí)行過程中,因爭奪資源而呵斥的一種相互等待的景象。此時稱系統(tǒng)處于死鎖形狀,這些永遠(yuǎn)在相互等待的線程稱為死鎖線程。產(chǎn)生死鎖的四個必要條件是:互斥條件:資源

20、每次只能被一個線程運(yùn)用。如前面的“線程同步代碼段,就是只能被一個線程運(yùn)用的典型資源;懇求與堅持條件:一個線程懇求資源,但由于某種緣由,該資源無法分配給它,于是該線程阻塞,此時,它對已獲得的資源堅持不放;不剝奪條件:進(jìn)程已獲得的資源,在未運(yùn)用完之前,不論其能否阻塞,無法強(qiáng)行剝奪;循環(huán)等待條件:假設(shè)干進(jìn)程之間相互等待,構(gòu)成一種頭尾相接的循環(huán)等待資源關(guān)系。這四個條件是死鎖的必要條件,只需系統(tǒng)發(fā)生死鎖,這些條件必然成立,而只需上述條件之一不滿足,就不會發(fā)生死鎖。3.4.2 案例分析以Java言語為例,死鎖普通來源于代碼段的同步,當(dāng)一段同步代碼被某線程運(yùn)轉(zhuǎn)時,其他線程能夠進(jìn)入堵塞形狀(無法搶占CPU),

21、而剛好在該線程中,訪問了某個對象,此時,除非同步鎖定被解除,否那么其他線程就不能訪問那個對象。這可以稱為“線程正在等待一個對象資源。假設(shè)出現(xiàn)一種極端情況,一個線程等候另一個對象,而另一個對象又在等候下一個對象,以此類推。這個“ 等候鏈假設(shè)進(jìn)入封鎖形狀,也就是說,最后那個對象等候的是第一個對象,此時,一切線程都會墮入無休止的相互等待形狀,呵斥死鎖。雖然這種情況并非經(jīng)常出現(xiàn),但一旦碰到,程序的調(diào)試將變得異常困難。在這里給出一個死鎖的案例,如代碼P03_10.java 這段程序也貌似沒有問題。但是和上一節(jié)的例子一樣,它也是很不平安的,這種不平安性也很難發(fā)現(xiàn)。察看run()函數(shù)中的代碼,當(dāng)th1運(yùn)轉(zhuǎn)后

22、,進(jìn)入代碼段1,鎖定了S1,假設(shè)此時th2運(yùn)轉(zhuǎn),搶占CPU,進(jìn)入代碼段3,鎖定S2,那么th1就無法運(yùn)轉(zhuǎn)代碼段2,但是又沒有釋放S1,此時,th2也就不能運(yùn)轉(zhuǎn)代碼段4。呵斥相互等待。為了模擬這個過程,我們在程序中添加讓其休眠的代碼,好讓另一個線程來搶占CPU。將P03_10.java的代碼改為P03_11.java該代碼中,添加了一行:程序休眠1000毫秒,讓另一個線程來搶占CPU。運(yùn)轉(zhuǎn),控制臺打印如下: 兩個線程墮入無休止的等待。其緣由是,線程th1進(jìn)入代碼段1后,線程2搶占CPU,鎖定了S2,而線程th1對S1的鎖定又沒有解除,呵斥線程th2無法運(yùn)轉(zhuǎn)下去,當(dāng)然,由于線程th2鎖定了S2,線

23、程th1也無法運(yùn)轉(zhuǎn)下去。死鎖是一個很重要的問題,它能導(dǎo)致整個運(yùn)用程序漸漸終止,尤其是當(dāng)開發(fā)人員不熟習(xí)如何分析死鎖環(huán)境的時候,還很難被分別和修復(fù)。 3.4.3 處理方案就言語本身來說,尚未直接提供防止死鎖的協(xié)助措施,需求我們經(jīng)過謹(jǐn)慎的設(shè)計來防止。普通情況下,我們主要是針對死鎖產(chǎn)生的四個必要條件來進(jìn)展破壞,用以防止和預(yù)防死鎖。在系統(tǒng)設(shè)計、線程開發(fā)等方面,留意如何不讓這四個必要條件成立,如何確定資源的合理分配算法,防止線程永久占據(jù)系統(tǒng)資源。以Java為例,Java并不提供對死鎖的檢測機(jī)制。但可以經(jīng)過java thread dump來進(jìn)展判別:普通情況下,當(dāng)死鎖發(fā)生時,Java虛擬機(jī)處于掛起形狀,th

24、read dump可以給出靜態(tài)穩(wěn)定的信息,從操作系統(tǒng)上察看,虛擬機(jī)的CPU占用率為零,這時可以搜集thread dump,查找waiting for monitor entry的線程,假設(shè)大量thread都在等待給同一個地址上鎖,闡明很能夠死鎖發(fā)生了。處理死鎖沒有簡單的方法,這是由于線程產(chǎn)生死鎖都各有各的緣由,而且往往具有很高的負(fù)載。從技術(shù)上講,可以用如下方法來進(jìn)展死鎖排除:可以吊銷陷于死鎖的全部線程??梢灾饌€吊銷陷于死鎖的進(jìn)程,直到死鎖不存在。從陷于死鎖的線程中逐個強(qiáng)迫放棄所占用的資源,直至死鎖消逝。提示:關(guān)于死鎖的檢測與解除,有很多重要算法,如資源分配算法、銀行家算法等。在操作系統(tǒng)的一些參

25、考資料中應(yīng)該可以進(jìn)展足夠了解。很多軟件產(chǎn)品內(nèi)置了死鎖處理戰(zhàn)略,可做參考。如: 數(shù)據(jù)庫死鎖。一個銜接占用了另一個銜接所需的數(shù)據(jù)庫鎖,它能夠阻塞另一個銜接。假設(shè)兩個或兩個以上的銜接相互阻塞,產(chǎn)生死鎖。該情況下,普通會強(qiáng)迫銷毀一個銜接通常是運(yùn)用最少的銜接,并回滾其事務(wù)。這將釋放一切與曾經(jīng)終了的事務(wù)相關(guān)聯(lián)的鎖,至少允許其他銜接中有一個可以獲取它們正在被阻塞的鎖。資源池耗盡死鎖。資源池太小,而每個線程需求的資源超越了池中的可用資源,產(chǎn)生死鎖。此時可以添加銜接池的大小或者重構(gòu)代碼,以便單個線程不需求同時運(yùn)用很多資源。3.5 線程控制平安3.5.1 平安隱患線程控制主要是對線程生命周期的一些操作,如暫停、繼

26、續(xù)、消亡等。本節(jié)以Java言語為例,講解線程控制中的一些平安問題。Java中提供了對線程生命周期進(jìn)展控制的函數(shù): stop():停頓線程; suspend():暫停線程的運(yùn)轉(zhuǎn); resume():繼續(xù)線程的運(yùn)轉(zhuǎn): destroy():讓線程銷毀;等等。線程生命周期中的平安問題主要表達(dá)在: 線程暫?;蛘呓K止時,能夠?qū)δ承┵Y源的鎖并沒有釋放,它所堅持的任何資源都會堅持鎖定形狀; 線程暫停之后,我們無法估計它什么時候會繼續(xù)(普通和用戶操作有關(guān)),假設(shè)對某個資源的鎖長期被堅持,其他線程在任何時候都無法再次訪問該資源,極有能夠呵斥死鎖。針對這個問題,為減少出現(xiàn)死鎖的能夠,Java 1.2中,將Threa

27、d的stop(),suspend(),resume()以及destroy()方法定義為“已過時方法,不再引薦運(yùn)用。3.5.2 案例分析如前所述,線程的暫停和繼續(xù),早期采用suspend()和resume()方法,但是容易發(fā)生死鎖。以線程暫停為例,調(diào)用suspend()的時候,目的線程會停下來,但卻依然持有在這之前獲得的鎖定。此時,其他任何線程都不能訪問鎖定的資源,除非被“掛起的線程恢復(fù)運(yùn)轉(zhuǎn)。假設(shè)它們想恢復(fù)目的線程,同時又試圖運(yùn)用任何一個鎖定的資源,就會呵斥死鎖。下面給出一個案例,來闡明這個問題。屏幕上不斷打印歡迎信息,點(diǎn)擊按鈕,打印任務(wù)暫停;再點(diǎn)擊,繼續(xù)打印。傳統(tǒng)代碼如P03_12.java

28、假設(shè)點(diǎn)擊“暫停按鈕,那么暫停打?。辉冱c(diǎn)擊,繼續(xù)打印。如上所述,該代碼實(shí)踐上在事件呼應(yīng)中用suspend()和resume()來控制線程的暫停和繼續(xù),是不平安的。3.5.3 處理方案處理該問題,常見的方法有如下幾種:1:當(dāng)需求暫停時,干脆讓線程的run()方法終了運(yùn)轉(zhuǎn)以釋放資源(實(shí)踐上就是讓該線程永久終了);繼續(xù)時,新開辟一個線程繼續(xù)任務(wù)。怎樣讓run()方法終了呢?普通可用一個標(biāo)志通知線程什么時候經(jīng)過退出本人的run()方法來中止本人的執(zhí)行。2:將線程暫?;蚶^續(xù),不運(yùn)用suspend()和resume(),可在Thread類中置入一個標(biāo)志,指出線程應(yīng)該活動還是掛起。假設(shè)標(biāo)志指出線程應(yīng)該掛起,便用wait()命其進(jìn)入等待形狀。假設(shè)標(biāo)志指出線程該當(dāng)恢復(fù),那么用一個notify()重新啟動線程。3:不引薦運(yùn)用stop()來終止阻塞的線程,而應(yīng)換用由Thread提供的interrupt()方法,以便中止并退出堵塞的代碼。3.6 進(jìn)程平安3.6.1 進(jìn)程概述進(jìn)程是一個執(zhí)行中的程序,對每一個進(jìn)程來說,都有本人獨(dú)立的一片內(nèi)存空間和一組系統(tǒng)資源。進(jìn)程由進(jìn)程控制塊、程序段、數(shù)據(jù)段三部分組成。在進(jìn)程概念中,每一個進(jìn)程的內(nèi)部數(shù)據(jù)和形狀都是完全獨(dú)立的。一個進(jìn)程可以包含假設(shè)干線程,線程可以協(xié)助運(yùn)用程序同時做幾件事(比如一個線程向

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論