開發(fā)的錯覺
今天聊一聊電腦和人腦的并發(fā)問題。
在計算機發(fā)展初期,CPU的計算能力非常有限,計算資源稀缺而昂貴。最早的時候一個CPU只能同時運行一個任務(wù),這簡直讓人無法忍受。什么叫做只能運行一個程序呢?這就像大學(xué)上自習(xí)占座一樣,一旦一本書、一張紙、一個包或一個活人占有了那個桌子,其他人就再也沒法用了,無論是這個人出去上廁所,踢球,你都不能去用那個座位,如果你賊膽包天敢偷著去坐,這時候就會有個神秘人突然拍拍你的肩膀告訴你「童靴,這里有人」,這就是常說的「見鬼的故事」。故事里的座位就是CPU,無論當(dāng)前任務(wù)在使用CPU進(jìn)行計算,還是在讀寫磁盤IO或進(jìn)行網(wǎng)絡(luò)交互,丫都得占著CPU,黑客極客和各種無證程序員們覺得,這,不,科,學(xué)!
于是大家試圖通過各種方式來改變這一現(xiàn)象。首先出場的是多通道程序,程序員們很快寫了一個監(jiān)控程序,發(fā)現(xiàn)當(dāng)前任務(wù)不用CPU計算時,就喚醒其他等待 CPU資源的程序,讓CPU資源能夠得到充分利用。但多通道的問題是調(diào)度乏力,不分青紅皂白和輕重緩急,不管是急診還是普通門診,該等都得等。
第二出場的是分時系統(tǒng),分時系統(tǒng)是一種協(xié)作模式,每個程序運行一小段時間都得主動把CPU讓出來給其他程序,這樣每個程序都有機會用到CPU一小段時間。這時操作系統(tǒng)的監(jiān)控程序也完善了一些,能夠處理相對復(fù)雜的請求。早期的Windows和Mac OS(注意沒有X)都是采用這種方式來調(diào)度程序的。分時系統(tǒng)的問題是,一旦某個程序死循環(huán),系統(tǒng)就沒招了,只能干等著,就像死機了一模一樣,程序員們說,這是不可接受的!
第三個隆重登場的是多任務(wù)系統(tǒng),程序員們讓操作系統(tǒng)接管了所有的硬件資源,變得更加高級智能,系統(tǒng)進(jìn)程開始分級,有的是特權(quán)級別,有的是平民級別(你就知道,在計算機世界都特么是這個樣子!),所有的應(yīng)用程序以進(jìn)程和線程方式運行,CPU的分配方式采用了搶占式,就是說操作系統(tǒng)可以強制把CPU的資源分配給目前最需要的程序。程序員們成功了,幾乎完美的控制了一切,并造成了很多任務(wù)都在同時運行的假象,如果用兩個字來形容的話,那就是「和諧」!目前OS X、Unix、Linux、Windows都是采用這種方式進(jìn)行任務(wù)管理的。
以上都是單核單CPU的情況,但無論線程間的切換多么快,這些都是并發(fā),而不是并行。
好吧,中間插播一段并發(fā)和并行的區(qū)別。并發(fā)的英文單詞是Concurrency,并行是Parallelism。如果一個系統(tǒng)支持兩個或多個動作(Action)同時存在,那就是一個并發(fā)系統(tǒng)。如果一個系統(tǒng)支持兩個或多個動作同時執(zhí)行,那就是一個并行系統(tǒng)。也就是說,單個CPU永遠(yuǎn)無法同時執(zhí)行兩個或以上的任務(wù),但是允許任務(wù)同時存在。所以,只有多核或多個CPU才可能發(fā)生并行,如果單核單CPU只能發(fā)生并發(fā)行為。
如果有人以為單核單CPU的并發(fā)就是同時執(zhí)行很多任務(wù),那么這是個錯覺。
不知道解釋清楚了木有。插播完畢!
終于,多核CPU和分布式系統(tǒng)被干出來了,一臺計算機可以擁有多顆CPU,每顆CPU可以有多核,同時,成千上萬臺的機器被連接在一起進(jìn)行計算,大家一看都暈了,史稱「云計算」。隨著硬件的變化,軟件技術(shù)同時開始革新,各種語言開始支持并行計算,比如Erlang/Scala的 Actor&Message模型,Go語言的goroutine機制,Java的ForkJoinPool,Objective-C的Grand Central Dispatch技術(shù),當(dāng)然還有Hadoop等分布式框架。
總之,到了目前這個階段,無論是并發(fā),還是并行,計算機和CPU都算是解放了,它們不僅在單臺機器上可以執(zhí)行并行計算,在橫向擴展上也變得隨心所欲,各種云平臺應(yīng)運而生,公有云私有云混合云balabala,反正是比較暈……
人腦就比較慘了,在電腦突飛猛進(jìn)的這幾十年里,幾乎沒有任何進(jìn)展,腦袋仍然只有一個,也沒有裂變出多核……
上文書談了電腦的并發(fā)和并行的事情,有讀者反饋,像一個有趣的教科書!我特么最煩教科書,就因為教科書,哥寫了幾年程序才把這些事捋清楚,為了讓你們不再重蹈覆轍,我容易嗎我!
好,下面我們談一下人腦的并發(fā),先看一個讀者反饋,你們感受一下:
看過一個關(guān)于人腦的理論,說不清是并發(fā)還是異步。有時候我們很努力的想一個問題,但卻怎么也想不起來,于是我們放棄了。但是大腦并沒有放棄,此時它會自動 起一個gorouting,繼續(xù)再大腦的各個角落去尋找這個記憶碎片,當(dāng)找到時執(zhí)行回調(diào)告訴你。而此時你可能正邊洗澡邊哼著小曲兒!
關(guān)于人腦的機制,其復(fù)雜程度超過CPU何止萬倍,比如上古奇人周伯通郭靖小龍女的雙手互搏到底是并發(fā)還是并行呢,Mac君萬不敢斷言,未來還是讓研究人腦圖譜的人去探索其真正的奧秘吧。我們在這篇文章中把「一心二用」或「一心多用」統(tǒng)稱為人腦的并發(fā)。
俗話說「一心不能二用」,這句話常常送給那些做事三心二意的人,但是我們真的不能一心多用嗎?或者說并發(fā)帶給我們的到底是效率的提升還是狀態(tài)的下降?關(guān)于這件事Mac君的看法是,不可一概而論?!负冒?,那位同學(xué)請把磚頭繼續(xù)放入懷中,我們還沒有講完」。
關(guān)于人腦的多任務(wù)處理,應(yīng)該從個人特點、所處環(huán)境和任務(wù)特性來考慮。
其實人腦天生就是用來處理多任務(wù)的,比如你可以一邊洗澡一邊唱歌,一邊看電影一邊磕瓜子還要注意不要被飛來的磚頭砸到等等,不過這樣的多任務(wù)都是在放松環(huán)境下的簡單任務(wù),對我們提升效率沒什么意義。
但是,當(dāng)我們在健身房跑步時聽英語,寫文章或編碼的時候聽歌(所有不讓聽音樂編程的公司都將死于心碎),坐地鐵的時候閱讀,步行的時候思考,這就變得非常有意義的,因為我們在一個相對寬松的環(huán)境下把復(fù)雜的邏輯任務(wù)和簡單的機械任務(wù)結(jié)合在一起,既不影響A,也不會干擾B,這種情況是我們優(yōu)先要采取的并發(fā)策略。
類似的事情,比如開車時聽英語,就要因人而異了。我有近10年的駕駛經(jīng)驗,喜歡開車,駕駛基本上已經(jīng)形成下意識的動作,從出發(fā)到目的地往往不會記得自己做了哪些操作,所以我經(jīng)常開車時聽英語并有所收獲。但有些人開車僅僅是駕駛已經(jīng)夠緊張忙亂了,倒一次車能車頭入絕不車尾進(jìn),開次長途出的汗夠洗澡的,那么就專心開車好了,車內(nèi)最好保持安靜或聽一些舒緩的音樂。
我曾經(jīng)看過一本叫做《錯覺》的書,書中有一段描述了一位機長在飛機飛行的過程中發(fā)現(xiàn)機上設(shè)備出了點小故障,于是他和副機長一起排查,接著又找來機械師,哥三忙的不亦樂乎,過了一段時間,有人問,誰在開飛機呢?這時飛機無人駕駛已經(jīng)很久了,等反應(yīng)過來之后,飛機已經(jīng)開始俯沖墜地,機上人員全部罹難!這種空難并不是意外,一架狀況良好的飛機直接撞向地面不是偶爾發(fā)生,這種現(xiàn)象在航空領(lǐng)域被稱作「可控飛行撞地」,其根本原因就是,人們太相信自己的多任務(wù)處理能力!
駕車雖然比駕駛飛機簡單多了,但同樣是一項非常危險的工作,所以我建議大家,聽聽音樂就好,另外千萬別玩手機。
還有一種情況就是,在同一時間做兩項或多項復(fù)雜任務(wù),比如你讓程序員在編碼的同時幫助別人解決問題,能不能做好?也許有人可以,但我的感覺是,這種安排效率反而會打折扣。 人們在很多時候會低估自己的能力,但在更多時候會高估自己。在復(fù)雜任務(wù)并發(fā)處理的時候,人腦往往會高估自己的處理能力,以為可以,其實任務(wù)的并行,上下文的切換,注意力的分散,都會讓你的效率大打折扣,所以設(shè)計模式中的職責(zé)單一原則不是蓋的,一個類盡可能只做一件事情,無論是效率還是后期維護(hù)都會好很多,人腦其實也是一樣。
總結(jié)一下: 1、簡單任務(wù)的并發(fā)是大腦天生的nature,每個人都不在不自覺的應(yīng)用。 2、在寬松的環(huán)境中讓簡單機械的任務(wù)和復(fù)雜有機的任務(wù)并行完成是非常不錯的做法,提高效率節(jié)省時間。 3、在高危環(huán)境中(駕駛、高空作業(yè)等等)我們應(yīng)該專心致志的只做當(dāng)前的工作。 4、對于復(fù)雜任務(wù),我們最好一件一件完成,即使有些人能夠同時處理多重任務(wù),那也需要長期的艱苦訓(xùn)練,比如郭靖君,你能否做到,就得看有沒有周伯通那樣的大哥!