網站首頁 編程語言 正文
Golang Goroutine和線程的區(qū)別 Golang,輕松學習
一、Golang Goroutine?
當使用者分配足夠多的任務,系統(tǒng)能自動幫助使用者把任務分配到 CPU 上,讓這些任務盡量并發(fā)運作。這種機制在 Go語言中被稱為 goroutine。
goroutine 是 Go語言中的輕量級線程實現(xiàn),由 Go 運行時(runtime)管理。Go 程序會智能地將 goroutine 中的任務合理地分配給每個 CPU。
使用每一個 go 關鍵字將會額外開啟一個新的協(xié)程 goroutine
二、線程是什么?
線程(英語:thread)是操作系統(tǒng)能夠進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運作單位。一條線程指的是進程中一個單一順序的控制流,一個進程中可以并發(fā)多個線程,每條線程并行執(zhí)行不同的任務。
三、調度的區(qū)別
1.線程調度
線程是系統(tǒng)調度的基本單位,線程作為調度與分配的基本單位,線程切換,僅需保存和設置少量寄存器的內容,開銷遠小于進程開銷。但這種線程切換仍然需要一個完整的上下文切換:即保存一個線程的狀態(tài)到內存,再恢復另外一個線程的狀態(tài),最后更新調度器的數(shù)據結構。某種意義上,這種操作還是很慢的。
2.goroutine 調度
Go運行的時候包涵一個自己的調度器,這個調度器使用一個稱為一個M:N調度技術,m個goroutine到n個os線程(可以用GOMAXPROCS來控制n的數(shù)量),Go的調度器不是由硬件時鐘來定期觸發(fā)的,而是由特定的go語言結構來觸發(fā)的,他不需要切換到內核語境,所以調度一個goroutine比調度一個線程的成本低很多。
Goroutine協(xié)程是一種協(xié)作任務控制機制,Goroutine可以理解為一種Go語言的協(xié)程。同時它可以運行在一個或多個線程上。而Goroutine協(xié)程的切換一般由程序員在代碼中顯式控制。它避免了上下文切換的額外耗費,兼顧了多線程的優(yōu)點,簡化了高并發(fā)程序的復雜。
四、??臻g的區(qū)別
1.線程占用
每個OS的線程都有一個固定大小的棧內存,通常是2MB,棧內存用于保存在其他函數(shù)調用期間哪些正在執(zhí)行或者臨時暫停的函數(shù)的局部變量。這個固定的棧大小,如果對于goroutine來說,可能是一種巨大的浪費。
以 64位環(huán)境的 JVM 為例,會默認固定為每個線程分配 1MB ??臻g,如果大小分配不當,便會出現(xiàn)棧溢出的問題。
2.goroutine 占用
- goroutine 所占用的內存,均在棧中進行管理 - goroutine 所占用的??臻g大小,由 runtime 按需進行分配 goroutine在生命周期開始只有一個很小的棧,典型情況是2KB, 在go程序中,一次創(chuàng)建十萬左右的goroutine也不罕見(2KB*100,000=200MB)。而且goroutine的棧不是固定大小,它可以按需增大和縮小,最大限制可以到1GB。 goroutine 相較于線程更加輕量,關鍵點就在于??臻g的動態(tài)分配,這樣便可以最大限度的利用內存資源。
五、標識的區(qū)別
1.線程標識
在大部分支持多線程的操作系統(tǒng)和編程語言中,線程有一個獨特的標識,通常是一個整數(shù)或者指針,這個特性可以讓我們構建一個線程的局部存儲,本質是一個全局的map,以線程的標識作為鍵,這樣每個線程可以獨立使用這個map存儲和獲取值,不受其他線程干擾。
2.goroutine 標識
goroutine中沒有可供程序員訪問的標識,原因是一種純函數(shù)的理念,不希望濫用線程局部存儲導致一個不健康的超距作用,即函數(shù)的行為不僅取決于它的參數(shù),還取決于運行它的線程標識。
總結
Golang 通過復雜的協(xié)程操作來實現(xiàn)我們的并發(fā)需求,golang是用戶線程與系統(tǒng)線程的對應關系是多對多,既能利用多核cpu資源,也能盡可能減少上下文切換成本,代價是go需要實現(xiàn)復雜的goroutine調度機制。
相比于N:1時所有用戶線程對應1個系統(tǒng)線程,無法利用多核cpu;1:1時1個用戶線程對應一個系統(tǒng)線程,上下文切換成本高。通過復雜的調度實現(xiàn)N:N時,即能利用多核cpu資源,也能盡可能減少上下文切換成本,成為Go語言最為人知的特點,天生支持高并發(fā)與高效。
原文鏈接:https://blog.csdn.net/moer0/article/details/123672726
相關推薦
- 2022-06-14 golang?channel管道使用示例解析_Golang
- 2024-03-13 TypeError: Cannot read property ‘get‘ of undefined
- 2024-01-31 linux部署項目, 報數(shù)據庫連接不上錯誤
- 2023-04-01 Pytorch基礎之torch.randperm的使用_python
- 2022-05-22 基于docker?部署canvas-lms的詳細步驟_docker
- 2023-03-03 PostgreSQL實時查看數(shù)據庫實例正在執(zhí)行的SQL語句實例詳解_PostgreSQL
- 2022-11-14 Asp.net?Core項目配置HTTPS支持_實用技巧
- 2022-07-24 .Net結構型設計模式之裝飾模式(Decorator)_基礎應用
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支