日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

Java平臺上進行多線程編程的缺陷

瀏覽:23日期:2024-03-03 10:26:38

Java 語言的并發(fā)編程 就其自身來說,并發(fā)編程是一種技術(shù),提供了操作的同時執(zhí)行,不論是在單一系統(tǒng)上還是分布在大量系統(tǒng)上。這類操作實際是一些指令順序,例如單獨某個頂級任務(wù)的子任務(wù),這類操作能夠并行執(zhí)行,或者是作為線程,或者是作為進程。線程和進程之間的本質(zhì)區(qū)別在于:進程通常是獨立的(例如獨立的地址空間),所以只能通過系統(tǒng)提供的進程間通信機制進行交互,而線程通常共享單一進程的狀態(tài)信息,能夠直接共享系統(tǒng)資源和內(nèi)存中的對象。

可以使用下面兩種方法之一,通過多個進程來實現(xiàn)并發(fā)。第一種方法是在同一個處理器上運行進程,由操作系統(tǒng)處理進程之間的上下文環(huán)境切換。(可以理解,這種切換要比同一進程內(nèi)多線程之間的上下文環(huán)境切換更慢。)第二種方法是構(gòu)建大規(guī)模的并行和復(fù)雜的分布式系統(tǒng),在不同的物理處理器上運行多個進程。

從內(nèi)建支持的角度來說,Java 語言通過線程提供并發(fā)編程;每個 JVM 都能支持許多線程同時執(zhí)行。可以用以下兩種方法之一在 Java 語言中創(chuàng)建線程:

繼承 java.lang.Thread 類。在這種情況下,已經(jīng)重寫的子類的 run() 方法必須包含實現(xiàn)線程運行時行為的代碼。要執(zhí)行這個代碼,需要實例化子類對象,然后調(diào)用對象的 start() 方法,這樣就可以在內(nèi)部執(zhí)行 run() 方法了。

創(chuàng)建 Runnable 接口的定制實現(xiàn)。這個接口只包含一個 run() 方法,在這個方法中,要放置應(yīng)用程序代碼。要執(zhí)行這個代碼,需要實例化實現(xiàn)類的對象,然后在創(chuàng)建新 Thread 時,把對象作為構(gòu)造函數(shù)的參數(shù)傳入。然后調(diào)用新創(chuàng)建的線程對象的 start() 方法,開始執(zhí)行控制的新線程。

線程安全性和同步

如果 Java 對象中的某個方法能夠安全地運行在多線程環(huán)境中,那么就稱該方法是 線程安全的。要獲得這種安全性,必須有一種機制,通過該機制,運行同一方法的多個線程就能夠同步其操作,這樣,在訪問相同的對象或代碼行時,就會只允許一個線程被處理。這種同步要求線程使用叫作 信號 的對象彼此進行溝通。

有一種類型的信號叫作 互斥信號 或 互斥體。顧名思義,這個信號對象的擁有權(quán)是互斥的,也就是說,在任意指定時間,只有一個線程能夠擁有互斥體。其他想獲得所有權(quán)的線程會被阻塞,它們必須等待,直到擁有互斥體的線程釋放互斥體。如果多個線程按順序排隊等候同一互斥體,那么在當前擁有者釋放它的時候,只有一個等候線程能夠得到它;其他線程將繼續(xù)阻塞。

在 1970 年代初,C.A.R. Hoare 和其他人共同開發(fā)了一個叫作 監(jiān)視器 的概念。一個 監(jiān)視器 就是一個代碼主體,它的訪問受到互斥體的保護。任何想執(zhí)行這個代碼的線程,都必須在代碼塊頂部得到關(guān)聯(lián)的互斥體,然后在底部再釋放它。因為在指定時間只有一個線程能夠擁有互斥體,所以這就有效地保證了只有擁有它的線程才能執(zhí)行監(jiān)視器的代碼塊。(受保護的代碼不需要相鄰 —— 例如,Java 語言中的每個對象都有一個與之關(guān)聯(lián)的監(jiān)視器。)

任何想在 Java 語言中進行線程編程的開發(fā)人員,都會立即把上面的內(nèi)容當成 synchronized 關(guān)鍵字所帶來的效果。可以確保包含在 synchronized 塊中的 Java 代碼在指定時間只被一個線程執(zhí)行。在內(nèi)部,可以由運行時將 synchronized 關(guān)鍵字轉(zhuǎn)換成某一種情況:所有的競爭線程都試圖獲得與它們(指線程)正在操作的對象實例關(guān)聯(lián)的那個(惟一的一個)互斥體。成功得到互斥體的線程將運行代碼,然后在退出 synchronized 塊時釋放互斥體。

等候和通知

wait/notify 構(gòu)造在 Java 語言的線程間通信機制中也扮演了重要的角色。基本的想法是:一個線程需要的某個條件可以由另外一個線程促成。這樣,條件的 wait 就可以得到滿足。一旦條件為真,那么引發(fā)條件的線程就會 notify 等候線程蘇醒,并從中止的地方繼續(xù)進行。

wait/notify 機制要比 synchronized 機制更難理解和判斷。要想判斷出使用 wait/notify 的方法的行為邏輯,就要求判斷出使用它的所有方法的邏輯。一次判斷一個方法,把該方法和其他方法隔離開,是對整體系統(tǒng)行為得出錯誤結(jié)論的可靠方式。顯然,這樣做的復(fù)雜性會隨著要判斷的方法的數(shù)量增長而迅速提高。

線程狀態(tài)

我前面提到過,必須調(diào)用新創(chuàng)建的線程的 start() 方法來啟動它的執(zhí)行。但是,僅僅是調(diào)用 start() 方法并不意味著線程會立即開始運行。這個方法只是把線程的狀態(tài)從 new 變成 runnable。只有在操作系統(tǒng)真正安排線程執(zhí)行的時候,線程狀態(tài)才會變成 running (從 runnable)。

典型的操作系統(tǒng)支持兩種線程模型 —— 協(xié)作式和搶占式。在協(xié)作式 模型中,每個線程對于自己對 CPU 的控制權(quán)要保留多久、什么時候放棄有最終意見。在這個模型中,因為可能存在某個無賴線程占住控制權(quán)不放,所以其他線程可能永遠無法得到運行。在 搶占式 模型中,操作系統(tǒng)本身采用基于時鐘“滴答的計時器,基于這個計時器,操作系統(tǒng)可以強制把控制權(quán)從一個線程轉(zhuǎn)移到另外一個線程。在這種情況下,決定哪個線程會得到下一次控制權(quán)的調(diào)度策略就有可能基于各種指標,例如相對優(yōu)先級、某個線程已經(jīng)等待執(zhí)行的時間長短,等等。

如果出于某些原因,處在 running 狀態(tài)的線程需要等候某個資源(例如,等候設(shè)備的輸入數(shù)據(jù)到達,或者等候某些條件已經(jīng)設(shè)定的通知),或者在試圖獲得互斥體的時候被阻塞,因此線程決定睡眠,那么這時它可以進入 blocked 狀態(tài)。當睡眠周期到期、預(yù)期輸入到達,或者互斥體當前的擁有者將其釋放并通知等候線程可以再次奪取互斥體時,阻塞的線程重新進入 runnable 狀態(tài)。

當線程的 run() 方法完成時(或者正常返回,或者拋出 RuntimeException 這樣的未檢測到異常),線程將終止。這時,線程的狀態(tài)是 dead。當線程死亡時,就不能通過再次調(diào)用它的 start() 方法來重新啟動它,如果那么做,則會拋出 InvalidThreadStateException 異常。

四個常見缺陷

正如我已經(jīng)展示過的,Java 語言中的多線程編程是通過語言支持的大量精心設(shè)計的構(gòu)造實現(xiàn)的。另外,還設(shè)計了大量設(shè)計模式和指導(dǎo)原則,來幫助人們了解這種復(fù)雜性帶來的許多缺陷。除此之外,多線程編程會很容易地在不經(jīng)意間把細微的 bug 帶進多線程代碼,而且更重要的是,這類問題分析和調(diào)試起來非常困難。接下來要介紹的是用 Java 語言進行多線程編程時將會遇到(或者可能已經(jīng)遇到過)的最常見問題的一個列表。

爭用條件

據(jù)說 爭用條件 存在于這樣的系統(tǒng)中:多個線程之間存在對共享資源的競爭,而勝出者決定系統(tǒng)的行為。Allen Holub 在他撰寫的文章 “programming Java threads in the real world 提供了一個帶有這樣 bug 的簡單的多線程程序示例。在沖突的訪問請求之間進行不正確同步的另一個更可怕的后果是 數(shù)據(jù)崩潰,此時,共享的數(shù)據(jù)結(jié)構(gòu)有一部分由一個線程更新,而另一部分由另一個線程更新。在這種情況下,系統(tǒng)的行為不是按照勝出線程的意圖進行,系統(tǒng)根本不按照任何一個線程的意圖行動,所以兩個線程最后都將以失敗告終。

死鎖

死鎖 的情況是指:線程由于等候某種條件變成真(例如資源可以使用),但是它等候的條件無法變成真,因為能夠讓條件變成真的線程在等候第一個線程“做某件事。這樣,兩個線程都在等候?qū)Ψ较炔扇〉谝徊剑远紵o法做事。

活動鎖

活動鎖 與 死鎖 不同,它是在線程實際工作的時候發(fā)生的,但這時還沒有完成工作。這通常是在兩個線程交叉工作的時候發(fā)生,所以第一個線程做的工作被另一個線程取消。一個簡單的示例就是:每個線程已經(jīng)擁有了一個對象,同時需要另外一個線程擁有的另外一個對象。可以想像這樣的情況:每個線程放下自己擁有的對象,撿起另外一個線程放下的對象。顯然,這兩個線程會永遠都運行在上鎖這一步操作上,結(jié)果是什么都做不成。(常見的真實示例就是,兩個人在狹窄的走廊相遇。每個人都禮貌地讓到另一邊讓對方先行,但卻在相同的時間都讓到同一邊了,所以兩個人還都沒法通過。這種情況會持續(xù)一些時間,然后兩個人都從這邊閃到那邊,結(jié)果還是一點進展也沒有。)資源耗盡

資源耗盡,又稱為 線程耗盡,是 Java 語言的 wait/notify 原語無法保證 live-ness 的后果。Java 強制這些方法要擁有它們等候或通知的對象的鎖。在某個線程上調(diào)用的 wait() 方法在開始等候之前必須釋放監(jiān)視器鎖,然后在從方法返回并獲得通知之后,必須再次重新獲得鎖。因此,Java 語言規(guī)范在鎖本身之外,還描述了一套與每個對象相關(guān)的 等候集(wait set)。一旦線程釋放了對象上的鎖(在 wait 的調(diào)用之后),線程就會放在這個等候集上。

多數(shù) JVM 實現(xiàn)把等候線程放在隊列中。所以,如果在通知發(fā)生的時候,還有其他線程在等候監(jiān)視器,那么就會把一個新線程放在隊列尾部,而它并不是下一個獲得鎖的線程。所以,等到被通知線程實際得到監(jiān)視器的時候,通知該線程的條件可能已經(jīng)不再為真,所以它不得不再次 wait。這種情況可能無限持續(xù)下去,從而造成運算工作上浪費(因為要反復(fù)把該線程放入等候集和從中取出)和線程耗盡。

貪心哲學家的寓言

演示這種行為的原型示例是 Peter Welch 教授描述的“聰明人沒有雞肉。在這個場景中考慮的系統(tǒng)是一所由五位哲學家、一位廚師和一個食堂組成的學院。所有的哲學家(除了一位)都要想想(在代碼示例中,考慮的時間是 3 秒)之后才去食堂取飯。而“貪心的哲學家則不想把時間浪費在思考上 —— 相反,他一次又一次地回到食堂,企圖拿到雞肉來吃。

廚師按照一批四份的定量準備雞肉,每準備好一批,就送到食堂。貪心的哲學家不斷地去廚房,但他總是錯過食物!事情是這樣的:他第一次到的時候,時間太早,廚師還沒開火。因此貪心的哲學家只好干等著(通過 wait() 方法調(diào)用)。在開飯的時候(通過 notify() 方法調(diào)用),貪心的哲學家再一次回到食堂排隊等候。但是這次,在他前來等候的時候,他的四位同事已經(jīng)到了,所以他在食堂隊列中的位置在他們后面。他的同事們把廚房送來的一批四份雞肉全部拿走了,所以貪心的哲學家又要在一邊等著了。 可憐(也可能是公平的) ,他永遠處在這個循環(huán)之外。

驗證的問題

一般來說,很難按照普通的規(guī)范對 Java 編程的多線程程序進行驗證。同樣,開發(fā)自動化工具對于常見的并發(fā)問題(例如死鎖、活動鎖和資源耗盡)進行完整而簡單的分析也不太容易——特別是在任意 Java 程序中或者在缺乏并發(fā)的正式模型的時候。

更糟的是,并發(fā)性問題出了名的變化多端、難于跟蹤。每個 Java 開發(fā)人員都曾經(jīng)聽說過(或者親自編寫過)這樣的 Java 程序:經(jīng)過嚴格分析,而且正常運行了相當一段時間,沒有表現(xiàn)出潛在的死鎖。然后突然有一天,問題發(fā)生了,結(jié)果弄得開發(fā)團隊經(jīng)歷許多的不眠之夜來試圖發(fā)現(xiàn)并修補根本原因。

一方面,多線程 Java 程序容易發(fā)生的錯誤非常不明顯,有可能在任意什么時候發(fā)生。另一方面,完全有可能這些 bug 在程序中從不出現(xiàn)。問題取決于一些不可知的因素。多線程程序的復(fù)雜本質(zhì),使得人們很難有效地對其進行驗證。沒有一套現(xiàn)成的規(guī)則可以找出多線程代碼中的這類問題,也無法確切地證明這些問題不存在,這些導(dǎo)致許多 Java 開發(fā)人員完全避開多線程應(yīng)用程序的設(shè)計和開發(fā),即使用并發(fā)和并行的方式對系統(tǒng)進行建模會非常棒,他們也不使用多線程。

確實想進行多線程編程的開發(fā)人員通常準備好了以下一個或兩個解決方案(至少是一部分):

長時間艱苦地測試代碼,找出所有出現(xiàn)的并發(fā)性問題,誠心地希望到應(yīng)用程序真正運行地時候已經(jīng)發(fā)現(xiàn)并修復(fù)了所有這類問題。

大量運行設(shè)計模式和為多線程編程建立的指導(dǎo)原則。但是,這類指導(dǎo)原則只在整個系統(tǒng)都按照它們的規(guī)范設(shè)計的時候才有效,沒有設(shè)計規(guī)則能夠覆蓋所有類型的系統(tǒng)。

雖然知道的人不多,但是對于編寫(然后驗證)正確的多線程應(yīng)用程序這一問題,還有第三個選項。使用稱為通信順序進程( Communicating Sequential Processes,CSP)的精確的線程同步的數(shù)學理論,可以在設(shè)計時最好地處理死鎖和活動鎖之類的問題。CSP 由 C.A.R. Hoare 與 20 世紀 70 年代后期設(shè)計,CSP 提供了有效的方法,證明用它的構(gòu)造和工具構(gòu)建的系統(tǒng)可以免除并發(fā)的常見問題。

結(jié)束語

在這份面向 Java 程序員的 CSP 全面介紹中,我把重點放在克服多線程應(yīng)用程序開發(fā)常見問題的第一步上,即了解這些問題。我介紹了 Java 平臺上目前支持的多線程編程構(gòu)造,解釋了它們的起源,討論了這類程序可能會有的問題。我還解釋了用正式理論在任意的、大型的和復(fù)雜的應(yīng)用程序中清除這些問題(即競爭冒險、死鎖、活動鎖和資源耗盡)或者證明這些問題不存在的困難。

標簽: Java
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
亚洲精选av| 一级欧美视频| 国产精品大片免费观看| 日韩av一级片| 日本色综合中文字幕| 午夜亚洲福利| 国产精品久久免费视频| 久久97视频| 日韩在线短视频| 欧美 日韩 国产精品免费观看| 久久久人人人| 不卡一区综合视频| 99综合视频| 日韩一区二区三区四区五区| 日韩精品成人| 欧美在线精品一区| 另类小说一区二区三区| 蜜桃精品在线| 视频在线观看一区二区三区| 天海翼亚洲一区二区三区| 日本不卡在线视频| 久久精品国产999大香线蕉| 成人啊v在线| 先锋影音久久久| 欧美日韩亚洲国产精品| 精品视频一区二区三区四区五区 | 日韩av免费大片| 91精品亚洲| 亚洲天堂日韩在线| 国产精品尤物| 久久91导航| 免费日本视频一区| 国产激情久久| 久久婷婷av| 无码日韩精品一区二区免费| 欧美激情亚洲| 尤物在线精品| 国产精品久久久免费| 天堂а√在线最新版中文在线| 99视频在线精品国自产拍免费观看| 日韩高清一区二区| 神马久久午夜| 伊人久久大香伊蕉在人线观看热v| 欧美日韩在线精品一区二区三区激情综合| 精品三级在线观看视频| 日韩视频不卡| 国产精品一区高清| 极品裸体白嫩激情啪啪国产精品| 日韩欧美久久| 欧美日韩在线观看首页| 蜜臀av在线播放一区二区三区| 美女尤物国产一区| 女同性一区二区三区人了人一| 日韩黄色在线观看| 日韩欧美看国产| 日韩在线电影| 日韩欧美一区二区三区在线视频| 在线精品观看| 午夜av不卡| 国产欧美在线观看免费| 五月天激情综合网| 欧美国产三级| 中文一区二区| 91亚洲人成网污www| 少妇精品在线| 国产国产精品| 国产v日韩v欧美v| 欧美一区二区三区久久精品| 国产精选在线| 奇米777国产一区国产二区| 久久精选视频| 久久久91麻豆精品国产一区| 亚洲一区二区av| 久久中文字幕av| 精品久久亚洲| 青青草伊人久久| 香蕉久久精品| 精品免费在线| 欧美一区网站| 视频一区欧美精品| 999国产精品| 久久精品国产亚洲一区二区三区| 蜜桃久久精品一区二区| 久久久久久色| 国产精品毛片| 群体交乱之放荡娇妻一区二区| 国产激情综合| 7m精品国产导航在线| 亚洲欧美日韩视频二区| 亚洲成av在线| 国产一区二区三区国产精品| 日韩和欧美一区二区三区| 亚洲欧美视频| 成人看片网站| 四虎国产精品免费观看| 国产日韩视频在线| 最新国产精品视频| 国产毛片一区| 激情自拍一区| 久久精品一区二区不卡| 成人午夜亚洲| 免费视频一区二区三区在线观看| 日韩黄色在线观看| 亚洲精品激情| 亚洲天堂免费| 影音先锋久久精品| 免费观看在线综合| 免费精品视频| 国产精品普通话对白| 欧美不卡高清| 久久香蕉国产| 欧美日韩激情| 精品一区亚洲| 亚洲成人精品| 欧美日一区二区| 国产一在线精品一区在线观看| 日韩高清欧美| 久久精品亚洲欧美日韩精品中文字幕| 欧美一级鲁丝片| 亚洲人成在线网站| 久久亚洲国产| 欧美精品自拍| 久久亚洲美女| 色综合视频一区二区三区日韩 | 欧美成人aaa| 精品视频亚洲| 午夜久久中文| 国产一在线精品一区在线观看| 国内精品99| 国产精品试看| 在线亚洲精品| 一区二区亚洲视频| 日本在线视频一区二区| 日韩高清一级| 国产极品嫩模在线观看91精品| 精品一区二区男人吃奶 | 成人台湾亚洲精品一区二区| 福利一区在线| 欧洲av一区二区| 99精品在线| 夜夜嗨av一区二区三区网站四季av| 欧美久久精品一级c片| 模特精品在线| 日韩精品高清不卡| 久久99免费视频| 欧洲亚洲一区二区三区| 99精品在线观看| 蜜桃久久av| 国产亚洲精品美女久久久久久久久久| 欧美国产中文高清| 999久久久国产精品| 亚洲欧美成人综合| 欧美亚洲免费| 国产成人精品福利| 久久要要av| 视频一区视频二区中文| 久久精品凹凸全集| 成人影视亚洲图片在线| 免费国产自久久久久三四区久久 | 九九在线精品| 中文字幕一区日韩精品| 欧美a在线观看| 亚洲a在线视频| 亚洲日本欧美| 国产成人免费视频网站视频社区| 99久久激情| 亚洲三区欧美一区国产二区| 91综合久久爱com| 色综合五月天| 亚洲一区国产一区| 91福利精品在线观看| 成人在线超碰| 午夜亚洲一区| 精品国产精品国产偷麻豆| 成人av二区| 久久99偷拍| 91久久黄色| 久久不卡国产精品一区二区| 91精品在线观看国产| 日本视频在线一区| 欧美亚洲国产精品久久| 日本精品久久| 日韩欧美一区免费| 日韩不卡一区二区三区| 香蕉成人av| 国产精品日本一区二区不卡视频 | 久久影院午夜精品| 一区二区国产在线观看| 国产美女高潮在线观看| 综合一区av| 丝袜av一区| 视频一区二区三区中文字幕| 欧美激情日韩| 蜜桃久久久久久| 欧美久久天堂| 国产免费av一区二区三区| 一区在线免费观看| av资源中文在线天堂| 91伊人久久| 99视频在线精品国自产拍免费观看|