冒號(hào)課堂§2.4:并發(fā)范式

          冒號(hào)課堂

          第二課 重要范式(4)

           

           2.4并發(fā)范式——合作與競(jìng)爭(zhēng)

          在合作中競(jìng)爭(zhēng),在競(jìng)爭(zhēng)中合作                                           ——《競(jìng)合》

          關(guān)鍵詞:編程范式,并發(fā)式編程,線程,進(jìn)程,過(guò)程式,函數(shù)式,邏輯式,對(duì)象式

          摘要:并發(fā)式編程簡(jiǎn)談

           
          提問(wèn)


          • 并發(fā)式編程有何特點(diǎn)?
          • 并發(fā)式編程有哪些好處?
          • 合理的并發(fā)式編程設(shè)計(jì)應(yīng)滿足哪些條件?

           講解

           逗號(hào)好奇地問(wèn):“還有其他類型的編程范式嗎?”

          “不但有,而且有很多。”冒號(hào)喝了一口水,悠悠地說(shuō),“并發(fā)式編程concurrent programming)就是其中之一。”

          嘆號(hào)有些驚訝:“并發(fā)式編程也算一種范式?它似乎更像是提供運(yùn)行效率的一種手段。”

          “大謬不然。”冒號(hào)搖搖頭,“真正的并發(fā)式編程,絕不只是調(diào)用線程[1]API或使用synchronizedlock之類的關(guān)鍵字那么簡(jiǎn)單。從宏觀的架構(gòu)設(shè)計(jì),到微觀的數(shù)據(jù)結(jié)構(gòu)、流程控制乃至算法,相比通常的串行式編程都可能發(fā)生變化。隨著硬件性能和用戶需求的雙重提升,并發(fā)式編程已成為不可回避的主題。毫不夸張地說(shuō),并發(fā)式編程是繼OOP之后又一場(chǎng)思想和技術(shù)上的革命。只是相比OOP,盡管年齡相仿,但語(yǔ)言上不夠支持,標(biāo)準(zhǔn)上不夠統(tǒng)一,理論上不夠完善,因而這場(chǎng)革命更具破壞性建設(shè)性?,F(xiàn)在我們來(lái)看一個(gè)例子,比較兩種燒水泡茶的方案。”

          說(shuō)著冒號(hào)在黑板上寫下——

          方案一:洗茶杯;放茶葉;灌水壺;燒水;水開(kāi)后泡茶。

          方案二:灌水壺;在燒水的同時(shí),洗茶杯;放茶葉;水開(kāi)后泡茶。

          引號(hào)見(jiàn)多識(shí)廣:“我記得這好像是運(yùn)籌學(xué)中的例子,顯然方案二更佳。從編程的角度來(lái)看,方案一是串行式編程,方案二是并發(fā)式編程——燒水的線程與洗茶杯放茶葉的線程是同時(shí)進(jìn)行的。”

          “如果方案一也用并發(fā)式編程呢?”冒號(hào)追問(wèn)。

          引號(hào)一愣,隨即道:“必須先洗茶杯后放茶葉,洗茶杯放茶葉的同時(shí)也沒(méi)法燒水,至于泡茶,更得等水開(kāi)之后了。”

          句號(hào)明白了冒號(hào)的用意:“這就是說(shuō),單憑并發(fā)式編程并不能保證提高程序性能,還必須在程序設(shè)計(jì)上下功夫。”

          問(wèn)號(hào)繼續(xù)深究:“即便如此,如果硬件不支持,并發(fā)式編程也未必能提高效率啊。比如在一臺(tái)單處理器的主機(jī)上,多個(gè)線程只能是模擬的、邏輯上的并行,而非真正物理上的并行。”

          “這話有一定道理。”冒號(hào)有限度地表示贊同,“但設(shè)計(jì)者應(yīng)該未雨綢繆,總不能等到有了多處理器才想到并發(fā)式編程吧?再者,沒(méi)有多處理器,是不是可以利用多臺(tái)單處理器的主機(jī)同時(shí)運(yùn)算呢?退一步講,即使在一臺(tái)單處理器的情況下,并發(fā)式編程同樣可能提高性能。最典型的一個(gè)例子:當(dāng)一個(gè)線程因?yàn)榈却撤N資源而被堵塞時(shí),可以切換到其他線程而不至讓CPU閑置。更重要的一點(diǎn)是,難道除了縮短程序運(yùn)行時(shí)間外,并發(fā)式編程就沒(méi)有別的好處嗎?譬如打開(kāi)一個(gè)網(wǎng)頁(yè),你是希望瀏覽器邊下載邊顯示網(wǎng)頁(yè)呢,還是下載完成后再顯示?”

           “當(dāng)然是邊下載邊顯示啦。” 嘆號(hào)毫不猶豫地說(shuō),“如果每個(gè)網(wǎng)頁(yè)都是下載完成后再顯示,那還不把人給憋壞了!”

          逗號(hào)加了一句:“瀏覽器加載文字和加載圖像也應(yīng)分開(kāi)在不同的線程,如果用戶對(duì)文字部分不感興趣,不等圖像顯示就可直接關(guān)閉網(wǎng)頁(yè)了。”

          “如果網(wǎng)頁(yè)被提前關(guān)閉,那也是假用戶之手變相縮短了程序運(yùn)行時(shí)間。”冒號(hào)接過(guò)話來(lái),“還有一個(gè)常見(jiàn)的例子,包括瀏覽器在內(nèi)的許多應(yīng)用軟件在運(yùn)行中都會(huì)顯示一個(gè)進(jìn)程條。該進(jìn)程條的更新需要一個(gè)單獨(dú)的線程,從效率上看它起的作用是負(fù)面的,但大大提高了用戶體驗(yàn),是軟件人性化的表現(xiàn)。再舉一例,媒體播放器一般都會(huì)提供暫停、快進(jìn)、倒退、快放、慢放等按鈕,如果不采用多線程,它們將形同虛設(shè)。此處并發(fā)式編程的作用在于提高了軟件的響應(yīng)能力,也改善了用戶體驗(yàn)——有誰(shuí)愿意駕駛一輛啟動(dòng)后不能剎車、不能倒車、不能變速、油盡方停的汽車呢?”

          “豈止是不愿意,簡(jiǎn)直是恐怖!”嘆號(hào)加重了語(yǔ)氣。

          “對(duì)于操作系統(tǒng)、各種實(shí)時(shí)系統(tǒng)和諸如數(shù)據(jù)庫(kù)、網(wǎng)絡(luò)服務(wù)器等基于服務(wù)的系統(tǒng)來(lái)說(shuō),在響應(yīng)用戶請(qǐng)求的時(shí)間上和資源的合理分配上有著極高的要求,并發(fā)式編程更是不可或缺。”句號(hào)接著補(bǔ)充。

          問(wèn)號(hào)隨即又問(wèn):“并發(fā)式編程還有其他用處嗎?”

          冒號(hào)應(yīng)道:“不同編程范式采用不同的視角和方法來(lái)設(shè)計(jì)和開(kāi)發(fā)軟件。并發(fā)式編程以進(jìn)程為導(dǎo)向Process-Oriented)、以任務(wù)為中心將系統(tǒng)模塊化。我們都知道,模塊化在編程中是個(gè)好東西。”

          引號(hào)心存疑惑:“過(guò)程式中引入了函數(shù)模塊,對(duì)象式中引入了對(duì)象模塊,但并發(fā)式似乎沒(méi)有在語(yǔ)法上引入新型模塊,比如CJava中的線程其實(shí)不過(guò)是函數(shù)或方法的包裝而已。”

          “我猜你的意思是:在定義一個(gè)線程之前,其主函數(shù)已經(jīng)模塊化了,不能把功勞記在并發(fā)式編程上,對(duì)吧?”冒號(hào)笑問(wèn),“你不能孤立靜止地看待每個(gè)模塊,還要考慮到模塊之間的相互關(guān)聯(lián)和作用。相比串行式,并發(fā)式在模塊之間引入了新的通訊和控制方式。也就是說(shuō),原先的一些模塊的定義和劃分一定是建立在線程機(jī)制的基礎(chǔ)上的。如果失去線程的支持,它們的合理性自然會(huì)打上問(wèn)號(hào),說(shuō)不定整體設(shè)計(jì)都會(huì)受到牽連。這也體現(xiàn)了編程范式的滲透性和全局影響力。”

          教室上空彌漫的疑云一消而散。

          冒號(hào)進(jìn)一步指出:“除了用戶主觀上的需求和硬件客觀上的可能外,并發(fā)式顯得格外重要的另一深層原因是:許多程序是現(xiàn)實(shí)世界的模擬,而我們生活的世界不折不扣是并發(fā)式的。從某種意義上看,并發(fā)式的模擬比對(duì)象式的模擬更貼近世界。”

          引號(hào)再次提問(wèn):“并發(fā)式編程在設(shè)計(jì)上有什么要求?”

          “并發(fā)式編程以資源共享與競(jìng)爭(zhēng)為主線——又是對(duì)當(dāng)今世界形勢(shì)的一個(gè)逼真模擬。這意味著程序設(shè)計(jì)將圍繞進(jìn)程的劃分與調(diào)度、進(jìn)程之間的通訊與同步等等來(lái)展開(kāi)。合理的并發(fā)式設(shè)計(jì)需要諸多方面的權(quán)衡考量。”冒號(hào)說(shuō)著,放出一段幻燈片——

          • 軟件易于重用、維護(hù)、測(cè)試
          • 公平有效地利用資源,優(yōu)化程序性能如增大吞吐量、減少響應(yīng)時(shí)間、提高效率等
          • 保障進(jìn)程安全,防止競(jìng)態(tài)條件(Race Condition
          • 保持進(jìn)程活性,避免死鎖、饑餓、活鎖、資源枯竭等
          • 減少鎖開(kāi)銷、上下文切換等帶來(lái)的性能損失
          • 妥善處理多進(jìn)程在算法、調(diào)試等方面帶來(lái)的復(fù)雜性

          嘆號(hào)蹙眉:“并發(fā)式編程好是好,就是太復(fù)雜。”

          “天下沒(méi)有免費(fèi)的午餐。有所得,必有所失。” 冒號(hào)淡淡地說(shuō),“并發(fā)式編程當(dāng)然不容易,但也并非難以掌握。最重要的是,作為一個(gè)程序員,你不得不面對(duì)它。即使你不直接用并發(fā)式編程,你依賴的代碼和依賴你的代碼也可能用到;即使現(xiàn)在沒(méi)有用并發(fā)式,將來(lái)也可能用到。如果采取避而不理的鴕鳥(niǎo)政策,早晚會(huì)被人點(diǎn)中你的死穴。雖然目前不會(huì)對(duì)并發(fā)式編程作更深入的探討,但希望能引起你們足夠的重視。”

          句號(hào)談及他的感受:“相比OOP在語(yǔ)言上得到的支持,并發(fā)式的支持力度好像很不夠。”

          冒號(hào)點(diǎn)頭稱是:“這是由并發(fā)式的復(fù)雜性和成熟度決定的。另外,在究竟是在語(yǔ)言級(jí)別上支持并發(fā)、還是交由操作系統(tǒng)處理的問(wèn)題上,仁者見(jiàn)仁,智者見(jiàn)智。AdaJavaC#等選擇前者,在語(yǔ)法上對(duì)并發(fā)式編程有一定的支持;CC++等選擇后者,除了關(guān)鍵字volatile外,主要靠庫(kù)函數(shù)支持。專門為并發(fā)式而設(shè)計(jì)的語(yǔ)言大多僅限于學(xué)術(shù)研究而非商業(yè)應(yīng)用,Erlang語(yǔ)言[2]是少數(shù)的例外。順帶提一下,前面提到的聲明式語(yǔ)言具有無(wú)副作用的特性,尤其適合于并發(fā)式編程。

          問(wèn)號(hào)提了一個(gè)聽(tīng)似奇怪的問(wèn)題:“并發(fā)式與前面提到的對(duì)象式有無(wú)共通之處?

          “并發(fā)式與對(duì)象式雖是互相正交的兩種范式,倒真有些相通呢。”冒號(hào)回答,“它們均與三大核心范式正交,并且越來(lái)越廣泛地向它們滲透著;均為傳統(tǒng)編程的一種推廣——并發(fā)式進(jìn)程的個(gè)數(shù)為一時(shí)即為傳統(tǒng)的串行式編程,對(duì)象的方法個(gè)數(shù)為為零即為傳統(tǒng)的數(shù)據(jù)類型;均將整個(gè)程序系統(tǒng)分解為若干獨(dú)立的子系統(tǒng),不同的是一個(gè)以任務(wù)為單位,一個(gè)以對(duì)象為單位;子系統(tǒng)之間均能交流與合作,不同的是一個(gè)以競(jìng)爭(zhēng)為主題,一個(gè)以服務(wù)為主題。如果將程序系統(tǒng)視作公司,那么并發(fā)式系統(tǒng)是產(chǎn)品型公司,每個(gè)進(jìn)程是一名工人,其職責(zé)是執(zhí)行單一任務(wù);對(duì)象式系統(tǒng)是服務(wù)型公司,每個(gè)對(duì)象是一名服務(wù)員,其職責(zé)是提供系列服務(wù)。由此可見(jiàn),一名優(yōu)秀的程序設(shè)計(jì)師也應(yīng)該是一名優(yōu)秀的管理者。”

          句號(hào)提出:“迄今為止我們談到了五種范式,能否對(duì)它們簡(jiǎn)單概括一下?”

          “你提問(wèn)的時(shí)機(jī)把握得不錯(cuò)嘛。”冒號(hào)開(kāi)始如數(shù)家珍,“為便于記憶,我們不妨用‘一二三四五’來(lái)概括編程范式之最:最傳統(tǒng)的一個(gè)是命令式;最基本的兩個(gè)是命令式和聲明式;最核心的三個(gè)是命令式、函數(shù)式和邏輯式;最主要的四個(gè)是命令式、函數(shù)式、邏輯式和對(duì)象式;最重要的五個(gè)是命令式、函數(shù)式、邏輯式、對(duì)象式和并發(fā)式。最后,我們來(lái)對(duì)比一下五大范式。”

          少頃,黑板上出現(xiàn)幾行排比句——

          過(guò)程式:以過(guò)程為模塊的君主體系,模塊之間互相授命與聽(tīng)命

          函數(shù)式:以函數(shù)為模塊的數(shù)學(xué)體系,模塊之間互相替換與合成

          邏輯式:以斷言為模塊的邏輯體系,模塊之間互相歸納與演繹

          對(duì)象式:以對(duì)象為模塊的民主體系,模塊之間互相交流與服務(wù)

          并發(fā)式:以進(jìn)程為模塊的生產(chǎn)體系,模塊之間互相競(jìng)爭(zhēng)與合作

           

          “說(shuō)回并發(fā)式編程,它要求我們擺脫以往習(xí)慣的按部就班的思維方式,對(duì)編程提出了更高的挑戰(zhàn)。程序世界與現(xiàn)實(shí)世界一樣,呈百舸爭(zhēng)流、千帆競(jìng)發(fā)之勢(shì),不進(jìn)則退??!”言訖,冒號(hào)宣布,“第二堂課到此為止,歡迎下次光臨。”

           

            插語(yǔ)

          [1] 并發(fā)式編程中以進(jìn)程(process)或線程(thread)為基本單位。盡管它們有很大的差異,但為簡(jiǎn)明起見(jiàn),這里不加區(qū)分地交替使用兩個(gè)術(shù)語(yǔ)。

          [2] Erlang是由愛(ài)立信開(kāi)發(fā)的一種通用編程語(yǔ)言,支持函數(shù)式和并發(fā)式。

           

           。總結(jié)

          ·         并發(fā)式編程以進(jìn)程為導(dǎo)向、以任務(wù)為中心、以資源共享與競(jìng)爭(zhēng)為主線。

          ·         并發(fā)式編程有助于提高運(yùn)行效率、充分利用資源、提高軟件的響應(yīng)能力、改善用戶體驗(yàn),同時(shí)以進(jìn)程為單位將系統(tǒng)模塊化,更加真實(shí)地模擬現(xiàn)實(shí)世界。

          ·         合理的并發(fā)式設(shè)計(jì)應(yīng)該做到:軟件易于重用、維護(hù)和測(cè)試;有效地利用資源,優(yōu)化程序性能;保障進(jìn)程安全和活性;減少性能損失和復(fù)雜度。

          ·         對(duì)象式和并發(fā)式在傳統(tǒng)編程的基礎(chǔ)上,分別從不同的方向進(jìn)行拓展:對(duì)象式在數(shù)據(jù)類型上進(jìn)行推廣——允許運(yùn)算作為數(shù)據(jù)類型的成員;并發(fā)式在執(zhí)行順序上進(jìn)行推廣——允許不同運(yùn)算的執(zhí)行在時(shí)間上交替或者重合。它們與三大核心范式一道,組成了最重要的五大編程范式。

          ·         五大重要范式對(duì)比:

          范式

          體系

          模塊

          模塊關(guān)系

          過(guò)程式

          君主體系

          過(guò)程

          授命與聽(tīng)命

          函數(shù)式

          數(shù)學(xué)體系

          函數(shù)

          替換與合成

          邏輯式

          邏輯體系

          斷言

          歸納與演繹

          對(duì)象式

          民主體系

          對(duì)象

          交流與服務(wù)

          并發(fā)式

          生產(chǎn)體系

          進(jìn)程

          競(jìng)爭(zhēng)與合作

           
          “”參考

          [1] Abraham Silberschatz,Peter GalvinOperating System Concepts5ed.Reading,MAAddison-Wesley,1998155-235



          課后思考

          ·         在你所掌握的語(yǔ)言當(dāng)中,有哪些是命令式的?哪些是聲明式的?其中,命令式語(yǔ)言里有哪些聲明式的特征?聲明式的語(yǔ)言里有哪些命令式的特征?它們各自有哪些優(yōu)點(diǎn)和缺點(diǎn)?

          ·         你編寫的程序符合結(jié)構(gòu)化編程的原則嗎?

          ·         你接觸過(guò)函數(shù)式語(yǔ)言和邏輯式語(yǔ)言嗎?如果沒(méi)有,試著閱讀相關(guān)的入門書籍,體會(huì)它們與過(guò)程式迥然不同的風(fēng)味。(函數(shù)式語(yǔ)言推薦Haskell Scheme,邏輯式語(yǔ)言推薦Prolog

          ·         相比純過(guò)程式的編程語(yǔ)言(如C語(yǔ)言),你認(rèn)為OO語(yǔ)言主要有哪些優(yōu)勢(shì)?又有哪些劣勢(shì)?

          ·         你認(rèn)為在并發(fā)式編程設(shè)計(jì)中,最重要的是什么?最困難的是什么?

          posted on 2008-11-04 00:33 鄭暉 閱讀(1250) 評(píng)論(2)  編輯  收藏 所屬分類: 冒號(hào)課堂

          評(píng)論

          # re: 冒號(hào)課堂§2.4:并發(fā)范式 2009-02-12 16:29 Todd

          最重要的是任務(wù)的抽象和建模,最困難的是任務(wù)間的協(xié)調(diào)和同步。

          --引用--
          你認(rèn)為在并發(fā)式編程設(shè)計(jì)中,最重要的是什么?最困難的是什么?  回復(fù)  更多評(píng)論   

          # re: 冒號(hào)課堂§2.4:并發(fā)范式[未登錄](méi) 2009-02-23 06:54 躺著讀書

          并發(fā)式基本上有2種模型:

          一是基于共享內(nèi)存的模型,這是java所采用的。
          一種是基于消息傳遞的模型,這是erlang采用的。

          基于共享模型的難在“鎖”,同步。
          基于消息傳遞的難在維持?jǐn)?shù)據(jù)結(jié)構(gòu)的統(tǒng)一性。

            回復(fù)  更多評(píng)論   

          導(dǎo)航

          統(tǒng)計(jì)

          公告

          博客搬家:http://blog.zhenghui.org
          《冒號(hào)課堂》一書于2009年10月上市,詳情請(qǐng)見(jiàn)
          冒號(hào)課堂

          留言簿(17)

          隨筆分類(61)

          隨筆檔案(61)

          文章分類(1)

          文章檔案(1)

          最新隨筆

          積分與排名

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 阳城县| 铜川市| 富裕县| 陆丰市| 乐至县| 栖霞市| 古交市| 恩平市| 杂多县| 卫辉市| 长沙县| 凯里市| 五常市| 绥中县| 旌德县| 金寨县| 齐河县| 当阳市| 保康县| 昭平县| 临颍县| 庆云县| 法库县| 新竹市| 镇宁| 克拉玛依市| 洛扎县| 城口县| 灯塔市| 青龙| 连平县| 普陀区| 福贡县| 长春市| 来宾市| 夏河县| 安平县| 无为县| 连州市| 区。| 拉孜县|