Golang CSP并發(fā)機(jī)制及使用模型
今天介紹一下 go語(yǔ)言的并發(fā)機(jī)制以及它所使用的CSP并發(fā)模型
CSP并發(fā)模型
CSP模型是上個(gè)世紀(jì)七十年代提出的,用于描述兩個(gè)獨(dú)立的并發(fā)實(shí)體通過共享的通訊 channel(管道)進(jìn)行通信的并發(fā)模型。 CSP中channel是第一類對(duì)象,它不關(guān)注發(fā)送消息的實(shí)體,而關(guān)注與發(fā)送消息時(shí)使用的channel。
Golang CSP
Golang 就是借用CSP模型的一些概念為之實(shí)現(xiàn)并發(fā)進(jìn)行理論支持,其實(shí)從實(shí)際上出發(fā),go語(yǔ)言并沒有,完全實(shí)現(xiàn)了CSP模型的所有理論,僅僅是借用了 process和channel這兩個(gè)概念。process是在go語(yǔ)言上的表現(xiàn)就是 goroutine 是實(shí)際并發(fā)執(zhí)行的實(shí)體,每個(gè)實(shí)體之間是通過channel通訊來實(shí)現(xiàn)數(shù)據(jù)共享。
Channel
Golang中使用 CSP中 channel 這個(gè)概念。channel 是被單獨(dú)創(chuàng)建并且可以在進(jìn)程之間傳遞,它的通信模式類似于 boss-worker 模式的,一個(gè)實(shí)體通過將消息發(fā)送到channel 中,然后又監(jiān)聽這個(gè) channel 的實(shí)體處理,兩個(gè)實(shí)體之間是匿名的,這個(gè)就實(shí)現(xiàn)實(shí)體中間的解耦,其中 channel 是同步的一個(gè)消息被發(fā)送到 channel 中,最終是一定要被另外的實(shí)體消費(fèi)掉的,在實(shí)現(xiàn)原理上其實(shí)是一個(gè)阻塞的消息隊(duì)列。
Goroutine
Goroutine 是實(shí)際并發(fā)執(zhí)行的實(shí)體,它底層是使用協(xié)程(coroutine)實(shí)現(xiàn)并發(fā),coroutine是一種運(yùn)行在用戶態(tài)的用戶線程,類似于 greenthread,go底層選擇使用coroutine的出發(fā)點(diǎn)是因?yàn)?,它具有以下特點(diǎn):
- 用戶空間 避免了內(nèi)核態(tài)和用戶態(tài)的切換導(dǎo)致的成本
- 可以由語(yǔ)言和框架層進(jìn)行調(diào)度
- 更小的棧空間允許創(chuàng)建大量的實(shí)例
可以看到第二條 用戶空間線程的調(diào)度不是由操作系統(tǒng)來完成的,像在java 1.3中使用的greenthread的是由JVM統(tǒng)一調(diào)度的(后java已經(jīng)改為內(nèi)核線程),還有在ruby中的fiber(半?yún)f(xié)程) 是需要在重新中自己進(jìn)行調(diào)度的,而goroutine是在golang層面提供了調(diào)度器,并且對(duì)網(wǎng)絡(luò)IO庫(kù)進(jìn)行了封裝,屏蔽了復(fù)雜的細(xì)節(jié),對(duì)外提供統(tǒng)一的語(yǔ)法關(guān)鍵字支持,簡(jiǎn)化了并發(fā)程序編寫的成本。
Goroutine 調(diào)度器
上節(jié)已經(jīng)說了,golang使用goroutine做為最小的執(zhí)行單位,但是這個(gè)執(zhí)行單位還是在用戶空間,實(shí)際上最后被處理器執(zhí)行的還是內(nèi)核中的線程,用戶線程和內(nèi)核線程的調(diào)度方法有:
N:1 多個(gè)用戶線程對(duì)應(yīng)一個(gè)內(nèi)核線程
1:1 一個(gè)用戶線程對(duì)應(yīng)一個(gè)內(nèi)核線程
M:N 用戶線程和內(nèi)核線程是多對(duì)多的對(duì)應(yīng)關(guān)系
golang 通過為goroutine提供語(yǔ)言層面的調(diào)度器,來實(shí)現(xiàn)了高效率的M:N線程對(duì)應(yīng)關(guān)系
調(diào)度示意
圖中
- M:是內(nèi)核線程
- P : 是調(diào)度協(xié)調(diào),用于協(xié)調(diào)M和G的執(zhí)行,內(nèi)核線程只有拿到了 P才能對(duì)goroutine繼續(xù)調(diào)度執(zhí)行,一般都是通過限定P的個(gè)數(shù)來控制golang的并發(fā)度
- G : 是待執(zhí)行的goroutine,包含這個(gè)goroutine的??臻g
- Gn : 灰色背景的Gn 是已經(jīng)掛起的goroutine,它們被添加到了執(zhí)行隊(duì)列中,然后需要等待網(wǎng)絡(luò)IO的goroutine,當(dāng)P通過 epoll查詢到特定的fd的時(shí)候,會(huì)重新調(diào)度起對(duì)應(yīng)的,正在掛起的goroutine。
Golang為了調(diào)度的公平性,在調(diào)度器加入了steal working 算法 ,在一個(gè)P自己的執(zhí)行隊(duì)列,處理完之后,它會(huì)先到全局的執(zhí)行隊(duì)列中偷G進(jìn)行處理,如果沒有的話,再會(huì)到其他P的執(zhí)行隊(duì)列中搶G來進(jìn)行處理。
總結(jié)
Golang實(shí)現(xiàn)了 CSP 并發(fā)模型做為并發(fā)基礎(chǔ),底層使用goroutine做為并發(fā)實(shí)體,goroutine非常輕量級(jí)可以創(chuàng)建幾十萬(wàn)個(gè)實(shí)體。實(shí)體間通過 channel 繼續(xù)匿名消息傳遞使之解耦,在語(yǔ)言層面實(shí)現(xiàn)了自動(dòng)調(diào)度,這樣屏蔽了很多內(nèi)部細(xì)節(jié),對(duì)外提供簡(jiǎn)單的語(yǔ)法關(guān)鍵字,大大簡(jiǎn)化了并發(fā)編程的思維轉(zhuǎn)換和管理線程的復(fù)雜性。
以上就是Golang CSP并發(fā)機(jī)制及使用模型的詳細(xì)內(nèi)容,更多關(guān)于Golang CSP并發(fā)模型的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Go語(yǔ)言學(xué)習(xí)之WaitGroup用法詳解
Go語(yǔ)言中的?WaitGroup?和?Java?中的?CyclicBarrier、CountDownLatch?非常類似。本文將詳細(xì)為大家講講WaitGroup的用法,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-06-06Go語(yǔ)言 channel如何實(shí)現(xiàn)歸并排序中的merge函數(shù)詳解
這篇文章主要給大家介紹了關(guān)于Go語(yǔ)言 channel如何實(shí)現(xiàn)歸并排序中merge函數(shù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-02-02go實(shí)現(xiàn)一個(gè)分布式限流器的方法步驟
項(xiàng)目中需要對(duì)api的接口進(jìn)行限流,本文主要介紹了go實(shí)現(xiàn)一個(gè)分布式限流器的方法步驟,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01