中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

GO并發編程使用方法是什么

發布時間:2023-02-24 11:39:56 來源:億速云 閱讀:133 作者:iii 欄目:開發技術

這篇文章主要介紹了GO并發編程使用方法是什么的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇GO并發編程使用方法是什么文章都會有所收獲,下面我們一起來看看吧。

啥是并發編程呢

指在一臺處理器上同時處理多個任務

此處說的同時,可不是同一個時間一起手拉手做同一件事情

并發是在同一實體上的多個事件,而這個事件在同一時間間隔發生的,同一個時間段,有多個任務執行,可是同一個時間點,只有一個任務在執行

為啥要有并發編程

隨著互聯網的普及,互聯網用戶人數原來越多,這對系統的性能帶來了巨大的挑戰。

我們要通過各種方式來高效利用硬件的性能(壓榨),從而提高系統的性能進而提升用戶體驗,提升團隊或者企業的競爭力。

并發是為了解決什么問題?目的是啥?

充分的利用好處理器的每一個核,以達到最高的處理性能,盡可能的運用好每一塊磚

可是由于現在我們使用的CPU,內存,IO三者之間速度不盡相同

我們為了提高系統性能,計算機系統會將這三者速度進行平衡,以達到最優的效果,都有如下措施:

  • 操作系統增加了進程線程,以分時復用 CPU,進而均衡 CPUI/O 設備的速度差異;

  • CPU 增加了緩存,以均衡與內存的速度差異;

  • 編譯程序優化指令執行次序,使得緩存能夠得到更加合理地利用。

說到進程和線程,他們都是干啥的呢,咱們順帶說一下?

進程是程序在操作系統中的一次執行過程

是 系統進行資源分配和調度的一個獨立單位

線程是進程的一個執行實體

是 CPU 調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。

一個進程可以創建和撤銷多個線程, 并且同一個進程中的多個線程之間可以并發執行。

講到并發編程不得不說并發和并行有啥區別?是不是總是有小伙伴弄不清楚他們到底是啥區別,好像一樣,又好像不一樣

并發和并行的區別

一言蔽之,區別如下:

并發

多線程程序在一個核的 CPU 上運行

并行

多線程程序在多個核的 CPU 上運行

并發就像多個小伙伴跑接力,同一個時間點只會有一個小伙伴在跑,互相有影響

GO并發編程使用方法是什么

并行就像是多個小伙伴同一個起點一起跑,互不干擾

GO并發編程使用方法是什么

我們需要記住一點,再強調一波:

并發不是并行

并發主要由切換時間片來實現"同時"運行

并行則是直接利用多核實現多線程的運行,

在 GO 可以設置使用核數,以發揮多核計算機的能力,不過設置核數都是依賴于硬件的

那么,講到GO的并發編程,就必須上我們的主角,那就是協程

協程 goroutine 是啥

協程是一種程序組件

是由子例程(過程、函數、例程、方法、子程序)的概念泛化而來的

子例程只有一個入口點且只返回一次,而協程允許多個入口點,可以在指定位置掛起和恢復執行。

協程和線程分別有啥特點嘞

協程

獨立的棧空間,共享堆空間,調度由用戶自己控制

本質上有點類似于用戶級線程,這些用戶級線程的調度也是自己實現的。

線程

一個線程上可以跑多個協程,協程是輕量級的線程

GO 高并發的原因是啥

  • goroutine 奉行通過通信來共享內存

  • 每個一個GO的實例有4~5KB的棧內存占用,并且由于 GO 實現機制而大幅減少的創建和銷毀開銷

  • Golang 在語言層面上就支持協程 goroutine

GOLANG并發編程涉及哪些知識點呢

  • 基本協程的原理,實現方式,雖然說,GO中使用協程很方便,可以我們必須要知其然而值其所以然

  • Goroutine 池

  • runtime 包的使用

  • Channel 通道

  • 定時器

  • 并發且安全的鎖

  • 原子操作

  • select 多路復用

  • 等等...

Goroutine的那些事

我們寫C/C++的時候,我們必然也是要實現并發編程

我們通常需要自己維護一個線程池,并且需要自己去包裝一個又一個的任務,同時需要自己去調度線程執行任務并維護上下文切換

且做線程池的時候,我們需要自己做一個線程管理的角色,靈活動態壓縮和擴容

可是能不能有這樣一種機制,我們只需要定義多個任務,讓系統去幫助我們把這些任務分配到CPU上實現并發執行

GO里面就正好有這樣的機制

goroutine 的概念類似于線程

goroutine 是由Go的運行時(runtime)調度和管理的

Go程序會智能地將 goroutine 中的任務合理地分配給每個CPU

Go 在語言層面已經內置了調度和上下文切換的機制

寫 GO 比較爽的一個地方是:

在GO里面,你不需要去自己寫進程、線程、協程

我們可以使用 goroutine 包

如何使用 goroutine

我們需要讓某個任務并發執行的時候,只需要把這個任務包裝成一個函數

專門開啟一個 goroutine 協程 去執行這個函數就可以了 , GO一個協程,很方便

一個 goroutine 必定對應一個函數,可以創建多個 goroutine 去執行相同的函數,只是多個協程都是做同一個事情罷了

我們先來使用一下協程,再來拋磚引玉,適當的分享一下

啟動單個協程

func Hi() {
    fmt.Println("this is Hi Goroutine!")
}
func main() {
    Hi()
    fmt.Println("main goroutine!")
}

我們一般調用函數是如上這個樣子的,效果如下

this is Hi Goroutine!
main goroutine!

其實我們調用協程的話,也與上述類似

我們可以使用 go 后面加上函數名字,來開辟一個協程,專門做函數需要執行的事情

func main() {
    go Hi() // 啟動一個goroutine 協程 去執行 Hi 函數
    fmt.Println("main goroutine!")

實際效果我們可以看到,程序只打印了 main goroutine!

main goroutine!

在程序啟動的時候,Go 程序就會為 main() 函數創建一個默認的 goroutine 協程

當 main() 函數返回的時候,剛開辟的另外一個 goroutine 協程 就結束了

所有在 main() 函數中啟動的 goroutine 協程 會一同結束,老大死了,其余的傀儡也灰飛煙滅了

我們也可以讓主協程等等一定子協程,待子協程處理完自己的事情,退出后,主協程再自己退出,這和我們寫C/C++進程 和 線程的時候,類似

簡單的,我們可以使用 time.sleep 函數來讓主協程阻塞等待

我們也可以使用 上述提到的 使用 select{} 來達到目的

當然也有其他的方式,后續文章會慢慢的分享到

多個協程

那么多個協程又是怎么玩的呢?

我們使用 sync.WaitGroup 來實現goroutine 協程的同步

package main

import (
	"fmt"
	"sync"
)

var myWg sync.WaitGroup

func Hi(i int) {
	// goroutine 協程 結束就 記錄 -1
	defer myWg.Done()
	fmt.Println("Hello Goroutine! the ", i)
}
func main() {

	for i := 0; i < 10; i++ {
		// 啟動一個goroutine 協程 就記錄 +1
		myWg.Add(1)
		go Hi(i)
	}

	// 等待所有記錄 的goroutine 協程 都結束
	myWg.Wait() 
}

會有如下輸出,每一個協程打印的數字并不是按照順序來的:

Hello Goroutine! the  9
Hello Goroutine! the  4
Hello Goroutine! the  2
Hello Goroutine! the  3
Hello Goroutine! the  6
Hello Goroutine! the  5
Hello Goroutine! the  7
Hello Goroutine! the  8
Hello Goroutine! the  1
Hello Goroutine! the  0

還是同樣的, 如果是主協程先退出,那么子協程還行繼續運行嗎?

毋庸置疑,主協程退出,子協程也會跟著退出

GO 中的協程

分享如下幾個點

GO中的棧是可增長的

一般都有固定的棧內存(通常為2MB),goroutine 的棧不是固定的,goroutine 的棧大小可以擴展到1GB

goroutine 是如何調度

這就不得不提 GPM

GPM是Go語言運行時(runtime)層面實現的,我們先簡單了解一下GPM分別代表啥

G

就是個 goroutine ,里面除了存放本 goroutine 信息外 還有與所在P的綁定等信息

P

Processor 管理著一組 goroutine 隊列

P 里面會存儲當前 goroutine 運行的上下文環境(函數指針,堆棧地址及地址邊界)

P 會對自己管理的 goroutine 隊列做一些調度(比如把占用CPU時間較長的 goroutine 暫停、運行后續的 goroutine)

當自己的隊列消費完了就去全局隊列里取,如果全局隊列里也消費完了會去其他P的隊列里搶任務。

M(machine)

是 Go 運行時(runtime)對操作系統內核線程的虛擬

M 與內核線程一般是一一映射的關系, 一個 groutine 最終是要放到 M上執行

這里的 P 與 M 一般也是一一對應的

P 管理著一組G 掛載在 M 上運行

當一個 G 長久阻塞在一個 M 上時,runtime 會新建一個M,

阻塞 G 所在的 P 會把其他的 G 掛載在新建的M上

這個時候,當舊的 G 阻塞完成或者認為其已經掛了的話,就會回收舊的 M

還有一點

P 的個數是通過 runtime.GOMAXPROCS 設定(最大256),這個數字也依賴于自己的硬件,在并發量大的時候會增加一些 P 和 M ,但不會太多。

關于“GO并發編程使用方法是什么”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“GO并發編程使用方法是什么”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

go
AI

武义县| 梁平县| 锡林浩特市| 乌苏市| 仙游县| 监利县| 凤山县| 小金县| 兴仁县| 蒙阴县| 汾阳市| 彰化市| 大英县| 仁化县| 兴化市| 昌都县| 内乡县| 微博| 富阳市| 唐山市| 巨野县| 西吉县| 北票市| 元阳县| 江山市| 界首市| 普宁市| 苍溪县| 乡城县| 遵义县| 阳东县| 沂南县| 海门市| 鸡泽县| 稷山县| 昌都县| 从化市| 司法| 屯昌县| 长阳| 奉新县|