網(wǎng)站首頁 編程語言 正文
今天介紹一下 go語言的并發(fā)機制以及它所使用的CSP并發(fā)模型
CSP并發(fā)模型
CSP模型是上個世紀(jì)七十年代提出的,用于描述兩個獨立的并發(fā)實體通過共享的通訊 channel(管道)進(jìn)行通信的并發(fā)模型。 CSP中channel是第一類對象,它不關(guān)注發(fā)送消息的實體,而關(guān)注與發(fā)送消息時使用的channel。
Golang CSP
Golang 就是借用CSP模型的一些概念為之實現(xiàn)并發(fā)進(jìn)行理論支持,其實從實際上出發(fā),go語言并沒有,完全實現(xiàn)了CSP模型的所有理論,僅僅是借用了 process和channel這兩個概念。process是在go語言上的表現(xiàn)就是 goroutine 是實際并發(fā)執(zhí)行的實體,每個實體之間是通過channel通訊來實現(xiàn)數(shù)據(jù)共享。
Channel
Golang中使用 CSP中 channel 這個概念。channel 是被單獨創(chuàng)建并且可以在進(jìn)程之間傳遞,它的通信模式類似于 boss-worker 模式的,一個實體通過將消息發(fā)送到channel 中,然后又監(jiān)聽這個 channel 的實體處理,兩個實體之間是匿名的,這個就實現(xiàn)實體中間的解耦,其中 channel 是同步的一個消息被發(fā)送到 channel 中,最終是一定要被另外的實體消費掉的,在實現(xiàn)原理上其實是一個阻塞的消息隊列。
Goroutine
Goroutine 是實際并發(fā)執(zhí)行的實體,它底層是使用協(xié)程(coroutine)實現(xiàn)并發(fā),coroutine是一種運行在用戶態(tài)的用戶線程,類似于 greenthread,go底層選擇使用coroutine的出發(fā)點是因為,它具有以下特點:
- 用戶空間 避免了內(nèi)核態(tài)和用戶態(tài)的切換導(dǎo)致的成本
- 可以由語言和框架層進(jìn)行調(diào)度
- 更小的棧空間允許創(chuàng)建大量的實例
可以看到第二條 用戶空間線程的調(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)度器,并且對網(wǎng)絡(luò)IO庫進(jìn)行了封裝,屏蔽了復(fù)雜的細(xì)節(jié),對外提供統(tǒng)一的語法關(guān)鍵字支持,簡化了并發(fā)程序編寫的成本。
Goroutine 調(diào)度器
上節(jié)已經(jīng)說了,golang使用goroutine做為最小的執(zhí)行單位,但是這個執(zhí)行單位還是在用戶空間,實際上最后被處理器執(zhí)行的還是內(nèi)核中的線程,用戶線程和內(nèi)核線程的調(diào)度方法有:
N:1 多個用戶線程對應(yīng)一個內(nèi)核線程
1:1 一個用戶線程對應(yīng)一個內(nèi)核線程
M:N 用戶線程和內(nèi)核線程是多對多的對應(yīng)關(guān)系
golang 通過為goroutine提供語言層面的調(diào)度器,來實現(xiàn)了高效率的M:N線程對應(yīng)關(guān)系
調(diào)度示意
圖中
- M:是內(nèi)核線程
- P : 是調(diào)度協(xié)調(diào),用于協(xié)調(diào)M和G的執(zhí)行,內(nèi)核線程只有拿到了 P才能對goroutine繼續(xù)調(diào)度執(zhí)行,一般都是通過限定P的個數(shù)來控制golang的并發(fā)度
- G : 是待執(zhí)行的goroutine,包含這個goroutine的棧空間
- Gn : 灰色背景的Gn 是已經(jīng)掛起的goroutine,它們被添加到了執(zhí)行隊列中,然后需要等待網(wǎng)絡(luò)IO的goroutine,當(dāng)P通過 epoll查詢到特定的fd的時候,會重新調(diào)度起對應(yīng)的,正在掛起的goroutine。
Golang為了調(diào)度的公平性,在調(diào)度器加入了steal working 算法 ,在一個P自己的執(zhí)行隊列,處理完之后,它會先到全局的執(zhí)行隊列中偷G進(jìn)行處理,如果沒有的話,再會到其他P的執(zhí)行隊列中搶G來進(jìn)行處理。
總結(jié)
Golang實現(xiàn)了 CSP 并發(fā)模型做為并發(fā)基礎(chǔ),底層使用goroutine做為并發(fā)實體,goroutine非常輕量級可以創(chuàng)建幾十萬個實體。實體間通過 channel 繼續(xù)匿名消息傳遞使之解耦,在語言層面實現(xiàn)了自動調(diào)度,這樣屏蔽了很多內(nèi)部細(xì)節(jié),對外提供簡單的語法關(guān)鍵字,大大簡化了并發(fā)編程的思維轉(zhuǎn)換和管理線程的復(fù)雜性。
原文鏈接:https://www.jianshu.com/p/36e246c6153d
相關(guān)推薦
- 2023-10-11 Mybatis-Plus條件構(gòu)造器的select
- 2022-06-12 C#自定義特性(Attribute)詳解_C#教程
- 2022-07-03 C#中的預(yù)定義類型與引用類型_C#教程
- 2022-07-31 C語言算法積累加tag的循環(huán)隊列_C 語言
- 2022-09-21 Python實現(xiàn)斐波那契數(shù)列的多種寫法總結(jié)_python
- 2022-11-26 使用HttpClient消費ASP.NET?Web?API服務(wù)案例_實用技巧
- 2022-09-03 C++中std::conditional的使用說明_C 語言
- 2023-02-23 Python利用Flask動態(tài)生成漢字頭像_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支