基本概念
并行和并發(fā)的區(qū)別
并行(parallel)
同時做某些事情煤裙,可以互不干擾的同時做幾件事。
舉例
:高速公路的車道系草,雙向4車道撕贞,所有車輛(數(shù)據(jù))可以互不干擾的在自己的車道上奔跑 (傳輸)。
在同一個時刻朋蔫,每條車道上可能同時有車輛在跑,是同時發(fā)生的概念罚渐。
如下圖所示,在t時刻可以有多個程序在執(zhí)行中驯妄,這樣就稱作并行荷并。(注意是同一時刻,不是同一個時間段)
并發(fā),(concurrency)
也是同時做某些事青扔,但是強調(diào),同一個時段做幾件事
鄉(xiāng)村公路一條車道源织,半幅路面出現(xiàn)了坑,交警指揮車輛走另外半幅路面翩伪,一個方向放行3分鐘,
停止方向雀鹃,換另一個方向放行幻工。發(fā)生了車輛同時要通過路面的事件,這就是并發(fā)。
如下圖所示黎茎,在T時間段內(nèi)可以有多個程序在執(zhí)行中囊颅,這樣就稱作并發(fā)。(注意是同一時間段傅瞻,一般這個時間段都指的是一個比較小的時間段踢代,不是同一個時刻)
經(jīng)典的生產(chǎn)者和消費者模型
比如有這樣一個生產(chǎn)者:一個賣煎餅果子的老奶奶,在沒有人買的時候可多做出幾個讓后放在架子上嗅骄,但是架子上的容量是有限的胳挎,比如最多能放10個,當(dāng)老奶奶想空余的時間多做出幾個放在架子上的時候每次都要看一看架子上有沒有空余的空間來放做出來的煎餅果子溺森。
比如有這樣的消費者:很多喜歡吃煎餅果子的小姐姐慕爬,都喜歡到老奶奶這里來買煎餅果子,如果小姐姐來的早屏积,在架子上有很多已經(jīng)做好了的煎餅果子医窿,然后小姐姐只要一來,看一看架子上是否有做好了的煎餅果子炊林,如果有就直接就買上走人了姥卢,但是晚來的小哥哥就沒有那么運氣好了,當(dāng)他來的時候架子上沒有了渣聚,只有等待著老奶奶做好了再賣給他独榴。
并發(fā)的解決
舉例“食堂打飯”:
很多人都肯定經(jīng)歷過,中午12點奕枝,下課后一望無際的腦袋都涌向食堂棺榔,(一小撮吃外賣的不算,并不是很多人家里都富有隘道,我也是只有吃食堂的份了)掷豺。特別是在12:00--12:30這個時間段人流量是最大的,這就叫做高并發(fā)薄声。為了使得食堂不會因為我們?nèi)藬?shù)太多了供應(yīng)不過來当船,崩掉了。所以食堂就要求我們排隊默辨,這就相當(dāng)于我們程序的消息隊列了德频,使用隊列的方式是一個可以解決并發(fā)的一種方法,雖然這種方法不一定很好缩幸,但是這是解決并發(fā)的一種方法壹置。
所以第一種解決辦法就是:隊列竞思、緩沖區(qū)
:
其實在食堂的打飯窗口前都有大片用來排隊的區(qū)域,這樣一個容納學(xué)生的區(qū)域就叫做緩沖區(qū)钞护,也就是在程序中暫時存放數(shù)據(jù)的地方盖喷。
緩沖區(qū)技術(shù)最開始提出來是用在處理內(nèi)存和CPU的速度問題的,大家都知道內(nèi)存讀寫很快难咕,但是我們CPU的計算能力更是日益更加的強大课梳,就出現(xiàn)了,內(nèi)存的讀寫數(shù)據(jù)跟不上CPU的處理數(shù)據(jù)余佃,然后人們就發(fā)明了cache(緩存)暮刃,CPU在處理數(shù)據(jù)的時候先把數(shù)據(jù)放入IO數(shù)據(jù)更快的cache中,然后再進行處理爆土,也可以理解成椭懊,cache就是一個數(shù)據(jù)臨時存放的地方,一般的計算機中都有多級緩存步势,CPU中一般也有cache氧猬,CPU中的cache一般稱作片內(nèi)cahe。
優(yōu)先隊列
假設(shè)今天是女神節(jié)坏瘩,學(xué)校為了給學(xué)校的女神們過節(jié)日盅抚,然后就出現(xiàn)了這樣一個規(guī)則,只要有女生來打飯就直接去最前面桑腮,不用跟在男生后面進行排隊。這樣的一個隊列蛉幸,在編程中就叫做優(yōu)先隊列破讨。
但是作為一個理工科大學(xué),女生還是寥寥無幾奕纫。
這種優(yōu)先隊列的方式還是不太好提陶,還有什么其他的方法呢?
我們可以這樣思考匹层,比如我們?nèi)ナ程么蝻埾栋剩缓蟛慌抨犃耍苯泳屯锩鏇_升筏,但是我們注意的是總有人先去到窗口里面撑柔,每個打飯的阿姨都只能給一個打飯的同學(xué)服務(wù)。也可以叫做這個同學(xué)把這樣阿姨占用了您访,在我們編程里面铅忿,當(dāng)你去請求一個資源的時候,如果你動作夠快灵汪,然后占用了這個資源檀训,然后就把這個資源給鎖上了柑潦。
所以第二種解決辦法就是:爭搶、鎖資源
:
但是這樣方法也不是很好峻凫,比如:有的同學(xué)為了搶著先打飯渗鬼,甚至爭的鼻青臉腫的。也比如說某個中學(xué)占用了一個打飯的阿姨荧琼,但是他在哪里想了一半天都沒有想好吃什么譬胎,后面判斷的同學(xué)就一直在后面等著,最后都爭吵起來了铭腕。還有一種情況就是比如某個同學(xué)平時也不鍛煉银择,身體素質(zhì)很差,更本就搶不贏其他的同學(xué)累舷。(在Linux內(nèi)核中其實也是這種爭搶機制浩考,比如我們?nèi)祟惖纳鐣绻闾蹙蛽尣悔A別人被盈,最后物競天擇……析孽,所以我們要努力學(xué)習(xí),增強自己只怎。)
雖然爭搶式的方式有很多的問題袜瞬,但是我們也不能只看缺點,同時爭搶式也有優(yōu)點身堡,比如:比如可以激勵我們的同學(xué)節(jié)省打飯的時間邓尤。
這學(xué)期我們學(xué)校的一個食堂就升級了,以前是同學(xué)們走到打飯的窗口前面贴谎,要吃什么然后再叫阿姨打汞扎,但是這樣效率并不是很高。所以這學(xué)期就換成了這樣的機制擅这,阿姨們提前把飯和菜提前用小點的碗和盤子盛好澈魄,然后同學(xué)們走到窗口前面就只要看著自己喜歡的菜和飯,端著就走了仲翎,到另外的地方買單就好痹扇。
所以第三種解決辦法就是:預(yù)處理
:
預(yù)處理的核心思想就是提前準備好用戶請求的資源。這不失為一個好的辦法溯香。
另外比如學(xué)校因為招到了很多的新生鲫构,食堂常常是人滿為患,所以學(xué)校就準備擴建了玫坛。另外又修了一棟樓來開食堂芬迄。導(dǎo)致打飯的窗口也變多了,但是這樣花費就大了,如果學(xué)校沒有這樣的積蓄是蓋不起大樓的禀梳。
所以第四種解決辦法就是:并行
:
比如我們最以前的8086芯片就只是單核心的杜窄,現(xiàn)在都是多核心的,處理的速度自然就提升了上來算途,比如打飯的窗口多了塞耕,同學(xué)們打到飯的速度也就變快了。
后面又接著分析嘴瓤,食堂的阿姨因為工作不積極扫外,或者說是業(yè)務(wù)能力不行,打飯的動作太慢了廓脆,出現(xiàn)了這種情況怎么辦呢筛谚,也就有解雇,然后招聘能力更好的打飯的阿姨了停忿。
所以第五種解決辦法就是:提速
:
這種提速就是更換新的東西驾讲,比如我們電腦運行速度越來越卡了,所以也就只用換更好的CPU席赂,速度更快的內(nèi)存吮铭。但是這種提升比較不常用,比如:我們現(xiàn)在就算你高薪請一個能力很強的阿姨但是颅停,人重視要累的谓晌,所以這種提升是有上限的。
我們應(yīng)該在坐飛機或者坐火車的時候癞揉,常常在安檢的時候地方前面有個很長的用鐵欄桿為其他的走廊纸肉,我們所有要過安檢的人先從這個走廊中依次排隊進入,當(dāng)排完隊后喊熟,后面就可以進入到各個安檢口柏肪,檢查身體和行李了。
所以第六種解決辦法就是:消息中間件
:
常見的消息中間件有RabbitMQ逊移、ActiveMQ ( Apache )预吆、RocketMQ (阿里Apache )龙填、kafka ( Apache )等胳泉。
當(dāng)然還有其他手段解決并發(fā)問題,但是已經(jīng)列舉除了最常用的解決方案,一般來說不同的并發(fā)場景用不同的策略,而策略可能是多種方式的優(yōu)化組合。
可能有的人無法區(qū)分上面我講的岩遗,消息隊列和消息中間件扇商,這兩種方法的區(qū)別,其實這兩種本質(zhì)上都是消息隊列的機制宿礁,只是前一種是在我服務(wù)的內(nèi)部實現(xiàn)案铺,二后一種是在服務(wù)的外部實現(xiàn)