首先你的理解是錯的,不管用戶態的API(syscall)是否是同步還是異步,在kernel層面都是異步的。
創新互聯建站-專業網站定制、快速模板網站建設、高性價比石家莊網站開發、企業建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式石家莊網站制作公司更省心,省錢,快速模板網站建設找我們,業務覆蓋石家莊地區。費用合理售后完善,十多年實體公司更值得信賴。
其實實現原理很簡單,就是利用C(嵌入匯編)語言可以直接修改寄存器(setcontext/setjmp/longjmp均是類似原理,修改程序指針eip實現跳轉,棧指針實現上線文切換)來實現從func_a調進去,從func_b返回出來這種行為。對于golang來說,func_a/func_b屬于不同的goroutine,從而就實現了goroutine的調度切換。
另外對于所有可能阻塞的syscall,golang對其進行了封裝,底層實際是epoll方式做的,注冊回調后切換到另一個runnable的goroutine。
參考:
Goroutine并發調度模型深度解析手擼一個協程池
Golang 的 goroutine 是如何實現的?
Golang - 調度剖析【第二部分】
OS線程初始棧為2MB。Go語言中,每個goroutine采用動態擴容方式,初始2KB,按需增長,最大1G。此外GC會收縮棧空間。
BTW,增長擴容都是有代價的,需要copy數據到新的stack,所以初始2KB可能有些性能問題。
更多關于stack的內容,可以參見大佬的文章。 聊一聊goroutine stack
用戶線程的調度以及生命周期管理都是用戶層面,Go語言自己實現的,不借助OS系統調用,減少系統資源消耗。
Go語言采用兩級線程模型,即用戶線程與內核線程KSE(kernel scheduling entity)是M:N的。最終goroutine還是會交給OS線程執行,但是需要一個中介,提供上下文。這就是G-M-P模型
Go調度器有兩個不同的運行隊列:
go1.10\src\runtime\runtime2.go
Go調度器根據事件進行上下文切換。
調度的目的就是防止M堵塞,空閑,系統進程切換。
詳見 Golang - 調度剖析【第二部分】
Linux可以通過epoll實現網絡調用,統稱網絡輪詢器N(Net Poller)。
文件IO操作
上面都是防止M堵塞,任務竊取是防止M空閑
每個M都有一個特殊的G,g0。用于執行調度,gc,棧管理等任務,所以g0的棧稱為調度棧。g0的棧不會自動增長,不會被gc,來自os線程的棧。
go1.10\src\runtime\proc.go
G沒辦法自己運行,必須通過M運行
M通過通過調度,執行G
從M掛載P的runq中找到G,執行G
NIO(非阻塞IO)是一種IO編程模型,Golang中的IO底層實現方式和java NIO模型一致,通俗點說就是都采用了EPOLL。 你在使用golang讀文件的時候,goroutine 會默默的掛起,只是你不知道,當讀完畢了,goroutine 再次恢復,但你不用擔心,goroutine 的掛起和恢復沒有java線程那樣可怕,你可以認為goroutine 的掛起和恢復就是保存和恢復幾個變量的值,其實也是這樣的。
剩下的就是goroutine 和 java線程的區別了,goroutine是用戶態的線程切換,java采用的是系統線程切換,用匯編語言描述是一個(java)調用int 80軟中斷,一個沒有。 意味著goroutine更輕量級,可以同時相應成千上萬的線程切換,java你創造上千個線程就有些吃力了。
因為java線程不能創造過多的線程,如果同時處理上萬上千的請求時候,就要考慮在幾十個線程來處理上萬上千的請求,這就出現了很多請求和線程不可能一一對應,所以通常做法是每個線程分別處理單個請求各個階段。好比流水線,請求是要加工的商品,每個線程處理一道工序,這樣做的好處是每人都做自己熟悉的,對于程序來說每個線程執行的代碼永遠都是自己很短的一塊,這樣根據局部優化原理,更具備CPU,內存親和力,利于JIT。說這樣多,就是說如果線程和請求不能一一對應,流水線式的并發編程很麻煩,閱讀性也很差,通常是線程A里面一段邏輯代碼,線程B又有另一處處理的邏輯代碼。
由于goroutine 的輕便,你可以將請求和goroutine 一一對應起來,不用考慮將請求在線程之間換來換去,只關心你的業務邏輯,這就是goroutine 的好處。
總結:
golang的goroutine讓你比java更容易編寫并發程序,但性能不會有差別(目前來說,golang性能還不能和java比,看過代碼就知道了,GC弱到爆),代碼不會減少,該寫的邏輯還得寫。ps,其實golang的(sched)go程切換代碼雖然原理和java的fork-join框架一樣,但是fork-join比golang的sched代碼牛逼不少,開始膜拜Doug Lea吧,golang還有很長的路要走。
當前名稱:go語言中的epoll Go語言中的Handle
新聞來源:http://vcdvsql.cn/article0/dopgcio.html
成都網站建設公司_創新互聯,為您提供外貿建站、域名注冊、商城網站、品牌網站設計、響應式網站、標簽優化
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯