摘要:兜底任務(wù),處理數(shù)據(jù)不一致?tīng)顟B(tài)的任務(wù)。什么是多線(xiàn)程多線(xiàn)程是并發(fā)的一種重要形式。通過(guò)具體的多線(xiàn)程問(wèn)題引出多線(xiàn)程編程中的關(guān)鍵點(diǎn)和對(duì)應(yīng)的工具與知識(shí)點(diǎn),輕松學(xué)會(huì)多線(xiàn)程編程。
這篇文章的目的并不是想教你如何造火箭(面試造火箭,工作擰螺絲),而是想通過(guò)對(duì)原理和應(yīng)用案例的有限度剖析來(lái)協(xié)助你構(gòu)建起并發(fā)的思維,并將操作系統(tǒng)的理論知識(shí)與工程實(shí)踐結(jié)合起來(lái),貫穿從學(xué)到會(huì)的全過(guò)程。當(dāng)然,雖然我們是從實(shí)用角度出發(fā),但具有實(shí)踐意義的深層次知識(shí)點(diǎn)永遠(yuǎn)會(huì)是面試中的殺手锏,這可比只能口頭造火箭的理論知識(shí)更吸引面試官。
本文適合誰(shuí):
希望能了解并發(fā)概念的初學(xué)者
需要理清并發(fā)概念與技術(shù)的工程師
對(duì)并發(fā)在工作中的應(yīng)用與其底層實(shí)現(xiàn)原理感興趣的讀者
在這篇文章中,你將了解到并發(fā)與多線(xiàn)程相關(guān)的一系列概念,通過(guò)一些例子我們可以在不糾結(jié)于具體的技術(shù)細(xì)節(jié)的情況下形成對(duì)并發(fā)與多線(xiàn)程相關(guān)的各種概念的抽象理解。有了這些概念以后,我們?cè)偃W(xué)習(xí)具體的理論和技術(shù)細(xì)節(jié)就是手到擒來(lái)的事了。
什么是并發(fā)?最近幾年淘寶發(fā)展得如火如荼,涌現(xiàn)出了一大批白手起家的賣(mài)家。想象一下你是一個(gè)剛剛起步的小賣(mài)家,自己運(yùn)營(yíng)一個(gè)服裝網(wǎng)店,每天都要自己打包發(fā)貨。剛開(kāi)始時(shí)生意一般,每天自己一個(gè)人一個(gè)小時(shí)就能干完。
隨著生意的蓬勃發(fā)展,發(fā)貨時(shí)間慢慢地從一個(gè)小時(shí)漲到了兩個(gè)小時(shí)、四個(gè)小時(shí),一次因?yàn)檠舆t發(fā)貨導(dǎo)致被投訴之后,你終于覺(jué)得該招更多的人了。很快,兩個(gè)小伙伴加入了你的事業(yè),打包速度開(kāi)始有了質(zhì)的提高。這就是最基本的并發(fā)了,每個(gè)人都可以看成是一個(gè)線(xiàn)程,同樣的工作量,干得人多了自然就快了。
所以并發(fā)就是通過(guò)多個(gè)執(zhí)行器同時(shí)執(zhí)行一個(gè)大任務(wù)來(lái)縮短執(zhí)行時(shí)間、提高執(zhí)行效率的方法。
數(shù)據(jù)競(jìng)爭(zhēng)但是好景不長(zhǎng),周末一盤(pán)貨,你發(fā)現(xiàn)少了不少。這辦公室里也沒(méi)遭賊,怎么就會(huì)少貨呢?細(xì)細(xì)一查快遞單,你發(fā)現(xiàn)竟然有幾單發(fā)重了。之后的幾天你都細(xì)細(xì)留意了一下發(fā)貨的過(guò)程,最后發(fā)現(xiàn)是因?yàn)槊總€(gè)人都會(huì)拿著一張發(fā)貨清單去備貨,如果有一些訂單不小心打印重復(fù)了,就有可能會(huì)被不同的人重復(fù)發(fā)貨。雖然數(shù)量不多,但是也很心痛啊。這個(gè)問(wèn)題產(chǎn)生的原因就是因?yàn)槊總€(gè)人在備貨之前拿到的訂單狀態(tài)(未發(fā)貨)在實(shí)際備貨時(shí)發(fā)生了變化(已由其他人發(fā)貨)。這種對(duì)一個(gè)共享數(shù)據(jù)(訂單的發(fā)貨狀態(tài))本應(yīng)獨(dú)占的讀取、檢查、修改過(guò)程,如果發(fā)生了并發(fā),這種情況就被稱(chēng)為數(shù)據(jù)競(jìng)爭(zhēng)。而這個(gè)讀取、檢查、修改的過(guò)程就被稱(chēng)為臨界區(qū),臨界區(qū)指的就是一個(gè)存在數(shù)據(jù)競(jìng)爭(zhēng)的代碼片段。
數(shù)據(jù)競(jìng)爭(zhēng)出現(xiàn)的根本原因是一個(gè)數(shù)據(jù)本來(lái)應(yīng)該只能由一個(gè)執(zhí)行器完整地執(zhí)行讀取、檢查、修改過(guò)程,但是如果出現(xiàn)了并發(fā),那么就沒(méi)辦法保證到了“修改”這一步時(shí)的數(shù)據(jù)還保持了“讀取”時(shí)的值了。
確定原因后,有人想到了一個(gè)好辦法,可以打印一張總的發(fā)貨清單,這樣所有人都必須以這個(gè)清單上的訂單是否發(fā)貨來(lái)確定是否要對(duì)訂單進(jìn)行備貨并發(fā)貨了。因?yàn)榍鍐沃挥幸环?,所以每次只能由一個(gè)人來(lái)修改訂單的發(fā)貨狀態(tài)。這種只能由一個(gè)執(zhí)行器進(jìn)行數(shù)據(jù)修改操作來(lái)避免發(fā)生數(shù)據(jù)競(jìng)爭(zhēng)問(wèn)題的做法就被稱(chēng)為互斥,也就是我們常說(shuō)的鎖了。
分布式并發(fā)概念 分布式因?yàn)槟愎芾淼卯?dāng),生意發(fā)展得很快,現(xiàn)在的辦公室里已經(jīng)堆不下所有衣服了。所以你又租了一個(gè)倉(cāng)庫(kù)來(lái)同樣進(jìn)行發(fā)貨。兩個(gè)地方都會(huì)進(jìn)行發(fā)貨,那么就可以把每一個(gè)倉(cāng)庫(kù)理解為一臺(tái)獨(dú)立的計(jì)算機(jī),這樣通過(guò)多臺(tái)計(jì)算機(jī)完成同一任務(wù)的方式就可以被稱(chēng)為分布式,這樣的一組計(jì)算機(jī)的集合就被稱(chēng)為集群。
這時(shí)候之前用一張紙質(zhì)的總發(fā)貨清單的數(shù)據(jù)競(jìng)爭(zhēng)解決方式就行不通了,所以我們需要把這張總發(fā)貨清單放到云端,讓大家可以通過(guò)網(wǎng)絡(luò)進(jìn)行編輯,但是每次只能一個(gè)人編輯。在這種情況下,我們可以把兩個(gè)倉(cāng)庫(kù)各自看成一臺(tái)計(jì)算機(jī)/進(jìn)程,而每個(gè)倉(cāng)庫(kù)里的人就是這個(gè)進(jìn)程中的線(xiàn)程。這樣的話(huà)這張總發(fā)貨清單就成為了一個(gè)分布式鎖,因?yàn)樗看沃荒苡幸粋€(gè)人編輯,所以是一個(gè)互斥鎖,或者簡(jiǎn)稱(chēng)為鎖;而因?yàn)樗梢员粌蓚€(gè)進(jìn)程/計(jì)算機(jī)(倉(cāng)庫(kù))共同使用,所以被稱(chēng)為是分布式鎖。
什么是進(jìn)程/線(xiàn)程?
可以簡(jiǎn)單地將進(jìn)程理解為我們電腦/手機(jī)上的一個(gè)應(yīng)用,同一臺(tái)手機(jī)上的每個(gè)App都是一個(gè)進(jìn)程,同一個(gè)App在每個(gè)手機(jī)上也是一個(gè)進(jìn)程。進(jìn)程和進(jìn)程之間可以理解為是兩個(gè)倉(cāng)庫(kù),互相之間物理隔離;而線(xiàn)程就是倉(cāng)庫(kù)里的每一個(gè)人,他們共享同一個(gè)辦公空間。這里的辦公空間就可以理解為操作系統(tǒng)中的虛擬內(nèi)存空間,但是本文主要討論并發(fā)相關(guān)的概念,就不繼續(xù)展開(kāi)了。
分布式數(shù)據(jù)不一致因?yàn)樯獗容^好,所以所有人都很忙。有時(shí)候就會(huì)因?yàn)橛幸恍┤穗m然在云端表格上已經(jīng)勾上了一個(gè)訂單,但是一忙就給忙忘了。其他人怕重復(fù)發(fā)貨又不會(huì)再去處理已經(jīng)勾上的訂單了,因?yàn)檫@樣導(dǎo)致的未發(fā)貨訂單讓店鋪被投訴了好多次,影響非常大。這種在并發(fā)過(guò)程中修改了數(shù)據(jù)狀態(tài)但是沒(méi)有完成后續(xù)執(zhí)行的情況就會(huì)出現(xiàn)數(shù)據(jù)不一致,即訂單已經(jīng)被勾上,但實(shí)際并沒(méi)有發(fā)貨。
但是作為聰明的老板,你又想到了解決的方法。每隔一小時(shí)兩個(gè)倉(cāng)庫(kù)就會(huì)各派一個(gè)人檢查一下已經(jīng)勾上的訂單是否已經(jīng)都打包完貼上快遞單了。這種每隔一段時(shí)間就檢查并處理遺漏的數(shù)據(jù)不一致訂單的任務(wù)就被稱(chēng)為兜底任務(wù)。而通過(guò)兜底任務(wù)實(shí)現(xiàn)的在最后所有訂單都會(huì)達(dá)到數(shù)據(jù)一致?tīng)顟B(tài)的情況就被稱(chēng)為最終一致性。
優(yōu)化方式大家可能早就覺(jué)得前面介紹的總發(fā)貨清單的方法太傻了,只要每個(gè)訂單都只打印一張發(fā)貨清單,由多帶帶一個(gè)人去負(fù)責(zé)分發(fā)清單就可以了,其他人只要處理好自己被分配到的訂單就可以了。最后再加上一個(gè)兜底任務(wù)對(duì)訂單的發(fā)貨情況進(jìn)行二次校驗(yàn)基本上就不會(huì)發(fā)生漏發(fā)或者重發(fā)的情況了。這種由一個(gè)執(zhí)行器進(jìn)行任務(wù)拆分,再由一組執(zhí)行器進(jìn)行處理,最后再由一個(gè)或一組執(zhí)行器進(jìn)行結(jié)果匯總的處理方式就是現(xiàn)在非常流行的map-reduce方法了。這種方法在大數(shù)據(jù)或者程序語(yǔ)言標(biāo)準(zhǔn)庫(kù)里都有大量的應(yīng)用,比如大數(shù)據(jù)領(lǐng)域赫赫有名的Hadoop和Java語(yǔ)言中的ForkJoinPool都使用了這種思想。
回顧在這篇文章中,我們涉及到了以下的技術(shù)名詞:
并發(fā),通過(guò)多個(gè)執(zhí)行器同時(shí)執(zhí)行一個(gè)大任務(wù)來(lái)縮短執(zhí)行時(shí)間、提高執(zhí)行效率的方法。
數(shù)據(jù)競(jìng)爭(zhēng),對(duì)一個(gè)共享數(shù)據(jù)本應(yīng)獨(dú)占的讀取、檢查、修改過(guò)程發(fā)生了并發(fā)的情況。
臨界區(qū),存在數(shù)據(jù)競(jìng)爭(zhēng)的代碼片段。
互斥鎖(也可以簡(jiǎn)稱(chēng)為“鎖”),同一時(shí)間只能由一個(gè)執(zhí)行器獲取的實(shí)體,用于實(shí)現(xiàn)對(duì)臨界區(qū)的互斥(只有一個(gè))訪(fǎng)問(wèn)。
分布式,通過(guò)多臺(tái)計(jì)算機(jī)完成同一任務(wù)的方式。
集群,一組完成同一任務(wù)的機(jī)器。
分布式鎖,在不同機(jī)器/進(jìn)程上提供互斥能力的鎖。
數(shù)據(jù)不一致,一系列操作不具有原子性,一部分執(zhí)行成功而另一部分沒(méi)有,導(dǎo)致不同數(shù)據(jù)之間存在矛盾,例如訂單已經(jīng)是發(fā)貨狀態(tài),但是實(shí)際沒(méi)有發(fā)貨。
兜底任務(wù),處理數(shù)據(jù)不一致狀態(tài)的任務(wù)。
最終一致性,通過(guò)兜底任務(wù)或其他方式保證數(shù)據(jù)不一致的情況最終會(huì)消失。
map-reduce,一種任務(wù)拆分-執(zhí)行-再合并的任務(wù)執(zhí)行方式,可以有效地利用多臺(tái)機(jī)器、多核CPU的性能。
后記因?yàn)椴l(fā)的知識(shí)范圍很大,而且對(duì)于一些抽象概念的傳遞必然會(huì)需要花費(fèi)一些篇幅,所以這個(gè)主題將會(huì)包含一系列文章,主要覆蓋以下主題:
什么是并發(fā)?
拋開(kāi)冗長(zhǎng)繁雜的技術(shù)點(diǎn),直接理解并發(fā)相關(guān)的各種概念。
什么是多線(xiàn)程?
多線(xiàn)程是并發(fā)的一種重要形式。通過(guò)具體的多線(xiàn)程問(wèn)題引出多線(xiàn)程編程中的關(guān)鍵點(diǎn)和對(duì)應(yīng)的工具與知識(shí)點(diǎn),輕松學(xué)會(huì)多線(xiàn)程編程。
常用工具中的并發(fā)實(shí)現(xiàn)
通過(guò)解析知名開(kāi)源工具中的并發(fā)方案實(shí)現(xiàn)來(lái)深入理解并發(fā)編程實(shí)踐。
有興趣的讀者可以繼續(xù)關(guān)注后續(xù)的文章,在之后的文章中會(huì)有對(duì)并發(fā)編程、操作系統(tǒng)原語(yǔ)、硬件原語(yǔ)等等理論與實(shí)踐知識(shí)的詳細(xì)介紹與案例。
對(duì)數(shù)據(jù)庫(kù)索引感興趣的讀者可以了解一下我之前的文章:
數(shù)據(jù)庫(kù)索引是什么?新華字典來(lái)幫你 —— 理解
數(shù)據(jù)庫(kù)索引融會(huì)貫通 —— 深入
20分鐘數(shù)據(jù)庫(kù)索引設(shè)計(jì)實(shí)戰(zhàn) —— 實(shí)戰(zhàn)
數(shù)據(jù)庫(kù)索引為什么用B+樹(shù)實(shí)現(xiàn)? —— 擴(kuò)展
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/73536.html
摘要:多線(xiàn)程不僅是后端開(kāi)發(fā)面試中非常熱門(mén)的一個(gè)問(wèn)題,也是各種高級(jí)工具框架與分布式的核心基石。有興趣的讀者可以參考本系列的第一篇文章來(lái)了解一下并發(fā)相關(guān)的基本概念當(dāng)我們?cè)谡f(shuō)并發(fā)多線(xiàn)程,說(shuō)的是什么。 多線(xiàn)程不僅是Java后端開(kāi)發(fā)面試中非常熱門(mén)的一個(gè)問(wèn)題,也是各種高級(jí)工具、框架與分布式的核心基石。但是這個(gè)領(lǐng)域相關(guān)的知識(shí)點(diǎn)涉及到了線(xiàn)程調(diào)度、線(xiàn)程同步,甚至在一些關(guān)鍵點(diǎn)上還涉及到了硬件原語(yǔ)、操作系統(tǒng)等更底...
摘要:在這個(gè)范圍廣大的并發(fā)技術(shù)領(lǐng)域當(dāng)中多線(xiàn)程編程可以說(shuō)是基礎(chǔ)和核心,大多數(shù)抽象并發(fā)問(wèn)題的構(gòu)思與解決都是基于多線(xiàn)程模型來(lái)進(jìn)行的。一般來(lái)說(shuō),多線(xiàn)程程序會(huì)面臨三類(lèi)問(wèn)題正確性問(wèn)題效率問(wèn)題死鎖問(wèn)題。 多線(xiàn)程編程或者說(shuō)范圍更大的并發(fā)編程是一種非常復(fù)雜且容易出錯(cuò)的編程方式,但是我們?yōu)槭裁催€要冒著風(fēng)險(xiǎn)艱辛地學(xué)習(xí)各種多線(xiàn)程編程技術(shù)、解決各種并發(fā)問(wèn)題呢? 因?yàn)椴l(fā)是整個(gè)分布式集群的基礎(chǔ),通過(guò)分布式集群不僅可以大...
摘要:最后,我們會(huì)通過(guò)對(duì)源代碼的剖析深入了解線(xiàn)程池的運(yùn)行過(guò)程和具體設(shè)計(jì),真正達(dá)到知其然而知其所以然的水平。創(chuàng)建線(xiàn)程池既然線(xiàn)程池是一個(gè)類(lèi),那么最直接的使用方法一定是一個(gè)類(lèi)的對(duì)象,例如。單線(xiàn)程線(xiàn)程池單線(xiàn)程線(xiàn)程 我們一般不會(huì)選擇直接使用線(xiàn)程類(lèi)Thread進(jìn)行多線(xiàn)程編程,而是使用更方便的線(xiàn)程池來(lái)進(jìn)行任務(wù)的調(diào)度和管理。線(xiàn)程池就像共享單車(chē),我們只要在我們有需要的時(shí)候去獲取就可以了。甚至可以說(shuō)線(xiàn)程池更棒,...
摘要:多線(xiàn)程編程就像一個(gè)沼澤,中間遍布各種各樣的陷阱。但是在多線(xiàn)程編程或者說(shuō)是并發(fā)編程中,有非常多的陷阱被埋在底層細(xì)節(jié)當(dāng)中。線(xiàn)程池類(lèi)中用于控制線(xiàn)程池狀態(tài)和線(xiàn)程數(shù)的控制變量就是一個(gè)類(lèi)型的字段。 多線(xiàn)程編程就像一個(gè)沼澤,中間遍布各種各樣的陷阱。大多數(shù)開(kāi)發(fā)者絕大部分時(shí)間都是在做上層應(yīng)用的開(kāi)發(fā),并不需要過(guò)多地涉入底層細(xì)節(jié)。但是在多線(xiàn)程編程或者說(shuō)是并發(fā)編程中,有非常多的陷阱被埋在底層細(xì)節(jié)當(dāng)中。如果不知...
摘要:官方對(duì)的解釋是進(jìn)程管理器。對(duì)并發(fā)訪(fǎng)問(wèn)的處理進(jìn)程和線(xiàn)程從代碼級(jí)別來(lái)講不支持多線(xiàn)程操作,不能像等語(yǔ)言一樣可以編寫(xiě)多線(xiàn)程代碼。 關(guān)于本篇文章的部分糾正,請(qǐng)參考這篇文章:http://www.cppblog.com/woaido... 首先搞清楚php-fpm與cgi的關(guān)系 CGI CGI是一個(gè)web server與cgi程序(這里可以理解為是php解釋器)之間進(jìn)行數(shù)據(jù)傳輸?shù)膮f(xié)議,保證了傳遞的...
閱讀 2848·2021-11-04 16:15
閱讀 3566·2021-09-29 09:35
閱讀 4172·2021-09-22 15:45
閱讀 1472·2019-08-30 15:55
閱讀 1760·2019-08-30 15:44
閱讀 2818·2019-08-29 12:56
閱讀 2783·2019-08-26 13:30
閱讀 2233·2019-08-23 17:00