版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、引言先拋開你所熟知的信號(hào)量、鎖、同步原語等技術(shù),思考這個(gè)問題:如何保證并發(fā) 讀寫的準(zhǔn)確性? 一個(gè)沒有任何并發(fā)編程經(jīng)驗(yàn)的程序員可能會(huì)覺得很簡單:這有什 么問題呢,同時(shí)讀寫能有什么問題,最多就是讀到過期的數(shù)據(jù)而已。一個(gè)理想的 世界當(dāng)然是這樣,只可惜實(shí)際上的機(jī)器世界往往隱藏了很多不容易被發(fā)覺的事情。 至少有兩個(gè)行為會(huì)影響這個(gè)結(jié)論:編譯器往往有指令重排序的優(yōu)化;例如程序員看到的源代碼是好句以4;,而實(shí)際上執(zhí)行的順序可能是以4;好3;,這是因?yàn)榫幾g器為了優(yōu)化執(zhí)行效 率可能對指令進(jìn)行重排序; 高級編程語言所支持的運(yùn)算往往不是原子化的;例如a += 3實(shí)際上包含了讀變量、加運(yùn)算和寫變量三次原子操作。既然整個(gè)
2、過程并不是原子化的,就意味著隨時(shí)有其它入侵者侵入修改數(shù)據(jù)。更為隱藏的例子:對于變量 的讀寫甚至可能都不是原子化的。不同機(jī)器讀寫變量的過程可能是不同的, 有些機(jī)器可能是64位數(shù)據(jù)一次性讀寫,而有些機(jī)器是32位數(shù)據(jù)一次讀寫。這就意味著一個(gè)64位的數(shù)據(jù)在后者的讀寫上實(shí)際上是分成兩次完成的!試想,如果你試圖讀取一個(gè)64位數(shù)據(jù)的值,先讀取了低32的數(shù)據(jù),這時(shí)另一個(gè)線程切進(jìn)來修改了整個(gè)數(shù)據(jù)的值,最后你再讀取高32的值,將高32和低32的數(shù)據(jù)拼成完整的值,很明顯會(huì)得到一個(gè)預(yù)期以外的數(shù) 據(jù)??雌饋恚麄€(gè)并發(fā)編程的世界里一切都是不確定的,我們不知道每次讀取的變量 到底是不是及時(shí)、準(zhǔn)確的數(shù)據(jù)。幸運(yùn)的是,很多語言都
3、有一個(gè)kappehs-before的 規(guī)那么,能幫助我們在不確定的并發(fā)世界里尋找一絲確定性。happens-before你可以把ka叩看作一種特殊的比擬運(yùn)算,就好像、一樣。對應(yīng)的,還有happe八s-aftec它們之間的關(guān)系也好像、一樣:Oncesync中還提供了一個(gè)。八cc的數(shù)據(jù)結(jié)構(gòu),用于控制并發(fā)編程中只執(zhí)行一次的邏輯,例如:var a striigvair oince sg八八ccfeme setapO (a = kelloj world11認(rèn)土仇(set up11)fiAM do”int() o 八 ce.Do(s 血?)fmt.Prmtfn(a)Mac twopsMt。go dopHn
4、t。go dopHht。)會(huì)打印 hello, world”兩次和“set up”一次。八”的happens-be- 規(guī)那么也很直觀:第一次執(zhí)行。八ccQo happen-before其余的。八ceQo應(yīng)用掌握了上述的基本k即ins-bcf”c規(guī)那么,可以結(jié)合起來分析更復(fù)雜的場景了,來 看這個(gè)例子:var a, b Mtfeme f() a = 1 / (I)b = 2/ (2)心八cgO print(b) / priit(a) / (4)fiAAC kvaii0 go K)gO)這里ka眸ChS-befC (2),ka叩c八s-bcf”c(4),但是與、之間以及與 (3)、(4)之間并沒有k
5、appc八s-bcf”c關(guān)系,這時(shí)候結(jié)果是不確定的,一種有趣的結(jié) 果是2、0,也就是(1)、(2)之間發(fā)生了指令重排序?,F(xiàn)在讓我們修改一下上面的 代碼,讓它按我們預(yù)期的邏輯運(yùn)行:要么打印0、0,要么打印1、2o使用鎖var a, b litvar lock Mutexfeme f()lock.LockQ / (2)4二工(2)b = 2 / lock.Unlock() / (4)心八c gO lock.LockO / priit(b) / (6)print / (7)(ock.Un(ock() / (8)八c kvxaiiaQ go fogO)回想下鎖的規(guī)那么:1.對鎖實(shí)例調(diào)用八次Unlock
6、 happ。八s-bcf。匕調(diào)用Lock作次,只要八這里,存在兩種可能:要么(4) happens-before,要么happen -before,會(huì)分 別推導(dǎo)出兩種結(jié)果: happe八s-bcfc (7) happens-before (2) happens-before (3), 以及(2) happe八s-before happens-befove (6) kappe八s-before (7),也就分別對應(yīng)“0、 0和 1、2兩種結(jié)果。使用通道 var a, b ivtvar c = iake(cka ict, 1) feme f() -c4 = 1(2)。= 2 / c一1)心八c g
7、O -cprint(b) / (6)priit(a) / (7)c b是否成立的過程,我們的做法很簡單:.基于一些簡單的公理;例如自然數(shù)的自然大?。?2工.基于比擬運(yùn)算符的傳遞性,也就是如果。泌且分c,那么ac判斷a happen-before b的過程也是類似的:根據(jù)一些簡單的明確的happens-before 關(guān)系,再結(jié)合ka曄的傳遞性,推導(dǎo)出我們所關(guān)心的W和r之間的 kappens-before 關(guān)系。happc八s-before 傳遞性:如果 a happe八s-befoK。b,且 b happe八s-before C, 貝lj a happe八s-bef。丫。C因此我們只需要了解這些
8、明確的ha叩加關(guān)系,就能在并發(fā)世界里尋找到 珍貴確實(shí)定性了。go語言中的happens-before關(guān)系具體的happens-before關(guān)系是因語言而異的,這里只介紹go語言相關(guān)的規(guī)那么, 感興趣可以直接閱讀官方文檔,有更完整、準(zhǔn)確的說明。自然執(zhí)行首先,最簡單也是最直觀的人即pens-before規(guī)那么:在同一個(gè)goroutine里,書寫在前的代碼happe八s-before書寫在后 的代碼。例如:a = 3; / (圾=4; / (2)那么Q) kappcns-bcforc (2)。我們上面提到指令重排序,也就是實(shí)際執(zhí)行的順序與書 寫的順序可能不一致,但h叩pens-before與指令重排
9、序并不矛盾,即使可能發(fā) 生指令重排序,我們依然可以說(1) happens-before (2)。初始化每個(gè)g。文件都可以有一個(gè)加土方法,用于執(zhí)行某些初始化邏輯。當(dāng)我們開始執(zhí) 行某個(gè)小川認(rèn)方法時(shí),go會(huì)先在一個(gè)goroutine里做初始化工作,也就是執(zhí)行所 有g(shù)o文件的i八江方法,這個(gè)過程中g(shù)o可能創(chuàng)立多個(gè)goroutine并發(fā)地執(zhí)行,因此通常情況下各個(gè)知t方法是沒有人叩飛八s-before關(guān)系的。關(guān)于,八才方法有兩條happe八s-before 規(guī)那么:.a包導(dǎo)入了 b包,此時(shí)b包的iiit方法happe八s-before 3包的所有代碼;.所有iiit方法happe八s-before恒/認(rèn)
10、方法;goroutinegoroutine相關(guān)的規(guī)那么主要是其創(chuàng)立和銷毀的:.goroutine 的創(chuàng)立 happens-砥。丫。其執(zhí)行;.goroutine的完成不保證k叩.八s-befo%任何代碼;第一條規(guī)那么舉個(gè)簡單的例子即可:var a stringface f() / (工)feme kelloQ a = heH。, world / (2)go f() )因?yàn)間oroutine的創(chuàng)立happe八s-before其執(zhí)行,所以happe八s-before (1),又因?yàn)樽匀粓?zhí)行的規(guī)那么(2) happe八s-before,根據(jù)傳遞性,所以happens-before (1),這樣保證了我
11、們每次打印出來的都是“hello world”而不是空字符串。第二條規(guī)那么是少見的否認(rèn)句式,同樣舉個(gè)簡單的例子: fu 八c kelloQ go 4 二keo |() / (工)仇力八土伉(a) / (2)由于goroutine的完成不保證happens-before任何代碼,因此(1) happens-before不成立,這樣我們就不能保證每次打印的結(jié)果都是“hell?!薄Mǖ劳ǖ纁hannel是go語言中用于goroutine之間通信的主要渠道,因此理解通道 之間的happens-before規(guī)那么也至關(guān)重要。1 .對于緩沖通道,向通道發(fā)送數(shù)據(jù) 叱吟-砥。匕從通道接收到數(shù)據(jù)結(jié)合一個(gè)例子:v
12、ar c =八 int, LO)vair a string fuM f() a = helloj world / (1)C - O / (2)go fo / -c / (4)/ (5)c是一個(gè)緩沖通道,因此向通道發(fā)送數(shù)據(jù)ka叩ChS-befc從通道接收到數(shù)據(jù),也就 是happen-More (4),再結(jié)合自然執(zhí)行規(guī)那么以及傳遞性不難推導(dǎo)出Q) happens-before (5),也就是打印的結(jié)果保證是hello world。有趣的是,如果我們把C的定義改為var c =3砥左加血)也就是無緩沖通道,上 面的結(jié)論就不存在了(注1),打印的結(jié)果不一定為“hello world”,這是因?yàn)椋?對于
13、無緩沖通道,從通道接收數(shù)據(jù)-before向通道發(fā)送數(shù) 據(jù)我們可以將上述例子稍微調(diào)整下:var c = kvake(cha a sWMgfeme f() a = heH。,world11 / (2)-c / (2)flAiaCgo f。c w := range work go ftmc。)limit - 1 / (1)w。 (2)/ Kw)select我們先套用一下上面的規(guī)那么,貝IJ:第1次第4次、第2次 (3)kappeias-before第5次、第3次happcns-before第6次,再結(jié)合傳遞性:”第 1 次(2)ka叩cns-befoHC 第 1 次happens-before 第
14、4 次Q)kappc八s-bcforc 第 4 次、第 2 次(2)happens -before 第 2 次happens -before 第 5 次 (l)kappens-before 第 5 次(2)”,簡單地說:第 1 次happens-before 第 4 次、”第2次(2)哂加* 第5次、第3次(2於-before第6次”這樣 我們雖然沒有做任何分批,卻事實(shí)上將workers分成三個(gè)一批、每批并發(fā)地執(zhí)行。 這就是通過這條happens-before規(guī)那么保證的。這個(gè)規(guī)那么理解起來其實(shí)也很簡單,C是通道的容量,如果無法保證第k次接收 happens-before第k+C次發(fā)送,那通道
15、的緩沖就不夠用了。注1:以上是官方文檔給的規(guī)那么和例子,但是筆者在嘗試將第一個(gè) 例子的c改成無緩沖通道后發(fā)現(xiàn)每次打印的依然穩(wěn)定是hell。world,并沒有出現(xiàn)預(yù)期的空字符串,也就是看起來happens-before 規(guī)那么依然成立。但既然官方文檔說無法保證,那我們開發(fā)時(shí)還是按 照happens-before不成立比擬好。鎖鎖也是并發(fā)編程里非常常用的一個(gè)數(shù)據(jù)結(jié)構(gòu)。go語言中支持的鎖主要有兩種: sgnc.Mutcx和sg八c.RWMutex,即普通鎖和讀寫鎖(讀寫鎖的原理可以參見另一篇文 章)。普通鎖的happens-before規(guī)那么也很直觀:1.對鎖實(shí)例調(diào)用八次Unlock happen-before調(diào)用Lock m次,只要八請看這個(gè)例子:var I yic.Mutexvair a string fimc f() a = hello,world11 / (1)I.UnlockQ / (2)fix八。加加八0 LLock。 / go f()/ (4)I.LockQ / priit(a
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年五金建材加盟協(xié)議
- 2025年分期家庭教育合同
- 《小島失蹤之謎》課件
- 2025年度綠色環(huán)保木材進(jìn)口與銷售合作合同范本大全4篇
- 二零二五年度冷鏈物流倉單質(zhì)押貸款服務(wù)協(xié)議2篇
- 二零二五年度競業(yè)禁止協(xié)議法律風(fēng)險(xiǎn)防控及合規(guī)咨詢合同
- 二零二五年度商業(yè)地產(chǎn)地下車位銷售及品牌推廣協(xié)議
- 二零二五年度股份有限公司私下股份分配與公司戰(zhàn)略協(xié)議書
- 二零二五版鋁單板幕墻材料采購專項(xiàng)合同4篇
- 二零二五年度離婚協(xié)議中兩個(gè)子女教育支持合同
- 玩具活動(dòng)方案設(shè)計(jì)
- Q∕GDW 516-2010 500kV~1000kV 輸電線路劣化懸式絕緣子檢測規(guī)程
- 遼寧省撫順五十中學(xué)2024屆中考化學(xué)全真模擬試卷含解析
- 2024年湖南汽車工程職業(yè)學(xué)院單招職業(yè)技能測試題庫及答案解析
- 家長心理健康教育知識(shí)講座
- GB/T 292-2023滾動(dòng)軸承角接觸球軸承外形尺寸
- 軍人結(jié)婚函調(diào)報(bào)告表
- 民用無人駕駛航空器實(shí)名制登記管理規(guī)定
- 北京地鐵6號(hào)線
- 航空油料計(jì)量統(tǒng)計(jì)員(初級)理論考試復(fù)習(xí)題庫大全-上(單選題匯總)
評論
0/150
提交評論