欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

瞅一眼就能學(xué)會(huì)的GO并發(fā)編程使用教程

 更新時(shí)間:2023年02月24日 10:50:23   作者:阿兵云原生  
隨著互聯(lián)網(wǎng)的普及,互聯(lián)網(wǎng)用戶人數(shù)原來越多,這對系統(tǒng)的性能帶來了巨大的挑戰(zhàn)。這個(gè)時(shí)候就需要并發(fā)編程了,本文為大家整理了詳細(xì)的GO并發(fā)編程使用教程,讓你看完就能學(xué)會(huì)

GO的并發(fā)編程分享

之前我們分享了網(wǎng)絡(luò)編程,今天我們來看看GO的并發(fā)編程分享,我們先來看看他是個(gè)啥

啥是并發(fā)編程呢

指在一臺處理器上同時(shí)處理多個(gè)任務(wù)

此處說的同時(shí),可不是同一個(gè)時(shí)間一起手拉手做同一件事情

并發(fā)是在同一實(shí)體上的多個(gè)事件,而這個(gè)事件在同一時(shí)間間隔發(fā)生的,同一個(gè)時(shí)間段,有多個(gè)任務(wù)執(zhí)行,可是同一個(gè)時(shí)間點(diǎn),只有一個(gè)任務(wù)在執(zhí)行

為啥要有并發(fā)編程

隨著互聯(lián)網(wǎng)的普及,互聯(lián)網(wǎng)用戶人數(shù)原來越多,這對系統(tǒng)的性能帶來了巨大的挑戰(zhàn)。

我們要通過各種方式來高效利用硬件的性能(壓榨),從而提高系統(tǒng)的性能進(jìn)而提升用戶體驗(yàn),提升團(tuán)隊(duì)或者企業(yè)的競爭力。

并發(fā)是為了解決什么問題?目的是啥?

充分的利用好處理器的每一個(gè)核,以達(dá)到最高的處理性能,盡可能的運(yùn)用好每一塊磚

可是由于現(xiàn)在我們使用的CPU,內(nèi)存,IO三者之間速度不盡相同

我們?yōu)榱颂岣呦到y(tǒng)性能,計(jì)算機(jī)系統(tǒng)會(huì)將這三者速度進(jìn)行平衡,以達(dá)到最優(yōu)的效果,都有如下措施:

  • 操作系統(tǒng)增加了進(jìn)程、線程,以分時(shí)復(fù)用 CPU,進(jìn)而均衡 CPUI/O 設(shè)備的速度差異;
  • CPU 增加了緩存,以均衡與內(nèi)存的速度差異;
  • 編譯程序優(yōu)化指令執(zhí)行次序,使得緩存能夠得到更加合理地利用。

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

進(jìn)程是程序在操作系統(tǒng)中的一次執(zhí)行過程

是 系統(tǒng)進(jìn)行資源分配和調(diào)度的一個(gè)獨(dú)立單位

線程是進(jìn)程的一個(gè)執(zhí)行實(shí)體

是 CPU 調(diào)度和分派的基本單位,它是比進(jìn)程更小的能獨(dú)立運(yùn)行的基本單位。

一個(gè)進(jìn)程可以創(chuàng)建和撤銷多個(gè)線程, 并且同一個(gè)進(jìn)程中的多個(gè)線程之間可以并發(fā)執(zhí)行。

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

并發(fā)和并行的區(qū)別

一言蔽之,區(qū)別如下:

并發(fā)

多線程程序在一個(gè)核的 CPU 上運(yùn)行

并行

多線程程序在多個(gè)核的 CPU 上運(yùn)行

并發(fā)就像多個(gè)小伙伴跑接力,同一個(gè)時(shí)間點(diǎn)只會(huì)有一個(gè)小伙伴在跑,互相有影響

并行就像是多個(gè)小伙伴同一個(gè)起點(diǎn)一起跑,互不干擾

我們需要記住一點(diǎn),再強(qiáng)調(diào)一波:

并發(fā)不是并行

并發(fā)主要由切換時(shí)間片來實(shí)現(xiàn)"同時(shí)"運(yùn)行

并行則是直接利用多核實(shí)現(xiàn)多線程的運(yùn)行,

在 GO 可以設(shè)置使用核數(shù),以發(fā)揮多核計(jì)算機(jī)的能力,不過設(shè)置核數(shù)都是依賴于硬件的

那么,講到GO的并發(fā)編程,就必須上我們的主角,那就是協(xié)程

協(xié)程 goroutine 是啥

協(xié)程是一種程序組件

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

子例程只有一個(gè)入口點(diǎn)且只返回一次,而協(xié)程允許多個(gè)入口點(diǎn),可以在指定位置掛起和恢復(fù)執(zhí)行。

協(xié)程和線程分別有啥特點(diǎn)嘞

協(xié)程

獨(dú)立的??臻g,共享堆空間,調(diào)度由用戶自己控制

本質(zhì)上有點(diǎn)類似于用戶級線程,這些用戶級線程的調(diào)度也是自己實(shí)現(xiàn)的。

線程

一個(gè)線程上可以跑多個(gè)協(xié)程,協(xié)程是輕量級的線程。

GO 高并發(fā)的原因是啥

  • goroutine 奉行通過通信來共享內(nèi)存
  • 每個(gè)一個(gè)GO的實(shí)例有4~5KB的棧內(nèi)存占用,并且由于 GO 實(shí)現(xiàn)機(jī)制而大幅減少的創(chuàng)建和銷毀開銷
  • Golang 在語言層面上就支持協(xié)程 goroutine

GOLANG并發(fā)編程涉及哪些知識點(diǎn)呢

  • 基本協(xié)程的原理,實(shí)現(xiàn)方式,雖然說,GO中使用協(xié)程很方便,可以我們必須要知其然而值其所以然
  • Goroutine 池
  • runtime 包的使用
  • Channel 通道
  • 定時(shí)器
  • 并發(fā)且安全的鎖
  • 原子操作
  • select 多路復(fù)用
  • 等等...

Goroutine的那些事

我們寫C/C++的時(shí)候,我們必然也是要實(shí)現(xiàn)并發(fā)編程

我們通常需要自己維護(hù)一個(gè)線程池,并且需要自己去包裝一個(gè)又一個(gè)的任務(wù),同時(shí)需要自己去調(diào)度線程執(zhí)行任務(wù)并維護(hù)上下文切換

且做線程池的時(shí)候,我們需要自己做一個(gè)線程管理的角色,靈活動(dòng)態(tài)壓縮和擴(kuò)容

可是能不能有這樣一種機(jī)制,我們只需要定義多個(gè)任務(wù),讓系統(tǒng)去幫助我們把這些任務(wù)分配到CPU上實(shí)現(xiàn)并發(fā)執(zhí)行

GO里面就正好有這樣的機(jī)制

goroutine 的概念類似于線程

goroutine 是由Go的運(yùn)行時(shí)(runtime)調(diào)度和管理的

Go程序會(huì)智能地將 goroutine 中的任務(wù)合理地分配給每個(gè)CPU

Go 在語言層面已經(jīng)內(nèi)置了調(diào)度和上下文切換的機(jī)制

寫 GO 比較爽的一個(gè)地方是:

在GO里面,你不需要去自己寫進(jìn)程、線程、協(xié)程

我們可以使用 goroutine 包

如何使用 goroutine

我們需要讓某個(gè)任務(wù)并發(fā)執(zhí)行的時(shí)候,只需要把這個(gè)任務(wù)包裝成一個(gè)函數(shù)

專門開啟一個(gè) goroutine 協(xié)程 去執(zhí)行這個(gè)函數(shù)就可以了 , GO一個(gè)協(xié)程,很方便

一個(gè) goroutine 必定對應(yīng)一個(gè)函數(shù),可以創(chuàng)建多個(gè) goroutine 去執(zhí)行相同的函數(shù),只是多個(gè)協(xié)程都是做同一個(gè)事情罷了

我們先來使用一下協(xié)程,再來拋磚引玉,適當(dāng)?shù)姆窒硪幌?/p>

啟動(dòng)單個(gè)協(xié)程

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

我們一般調(diào)用函數(shù)是如上這個(gè)樣子的,效果如下

this is Hi Goroutine!
main goroutine!

其實(shí)我們調(diào)用協(xié)程的話,也與上述類似

我們可以使用 go 后面加上函數(shù)名字,來開辟一個(gè)協(xié)程,專門做函數(shù)需要執(zhí)行的事情

func main() {
    go Hi() // 啟動(dòng)一個(gè)goroutine 協(xié)程 去執(zhí)行 Hi 函數(shù)
    fmt.Println("main goroutine!")

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

main goroutine!

在程序啟動(dòng)的時(shí)候,Go 程序就會(huì)為 main() 函數(shù)創(chuàng)建一個(gè)默認(rèn)的 goroutine 協(xié)程

當(dāng) main() 函數(shù)返回的時(shí)候,剛開辟的另外一個(gè) goroutine 協(xié)程 就結(jié)束了

所有在 main() 函數(shù)中啟動(dòng)的 goroutine 協(xié)程 會(huì)一同結(jié)束,老大死了,其余的傀儡也灰飛煙滅了

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

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

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

當(dāng)然也有其他的方式,后續(xù)文章會(huì)慢慢的分享到

多個(gè)協(xié)程

那么多個(gè)協(xié)程又是怎么玩的呢?

我們使用 sync.WaitGroup 來實(shí)現(xiàn)goroutine 協(xié)程的同步

package main

import (
	"fmt"
	"sync"
)

var myWg sync.WaitGroup

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

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

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

會(huì)有如下輸出,每一個(gè)協(xié)程打印的數(shù)字并不是按照順序來的:

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

還是同樣的, 如果是主協(xié)程先退出,那么子協(xié)程還行繼續(xù)運(yùn)行嗎?

毋庸置疑,主協(xié)程退出,子協(xié)程也會(huì)跟著退出

GO 中的協(xié)程

分享如下幾個(gè)點(diǎn)

GO中的棧是可增長的

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

goroutine 是如何調(diào)度

這就不得不提 GPM

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

G

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

P

Processor 管理著一組 goroutine 隊(duì)列

P 里面會(huì)存儲(chǔ)當(dāng)前 goroutine 運(yùn)行的上下文環(huán)境(函數(shù)指針,堆棧地址及地址邊界)

P 會(huì)對自己管理的 goroutine 隊(duì)列做一些調(diào)度(比如把占用CPU時(shí)間較長的 goroutine 暫停、運(yùn)行后續(xù)的 goroutine)

當(dāng)自己的隊(duì)列消費(fèi)完了就去全局隊(duì)列里取,如果全局隊(duì)列里也消費(fèi)完了會(huì)去其他P的隊(duì)列里搶任務(wù)。

M(machine)

是 Go 運(yùn)行時(shí)(runtime)對操作系統(tǒng)內(nèi)核線程的虛擬

M 與內(nèi)核線程一般是一一映射的關(guān)系, 一個(gè) groutine 最終是要放到 M上執(zhí)行

這里的 P 與 M 一般也是一一對應(yīng)的

P 管理著一組G 掛載在 M 上運(yùn)行

當(dāng)一個(gè) G 長久阻塞在一個(gè) M 上時(shí),runtime 會(huì)新建一個(gè)M,

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

這個(gè)時(shí)候,當(dāng)舊的 G 阻塞完成或者認(rèn)為其已經(jīng)掛了的話,就會(huì)回收舊的 M

還有一點(diǎn)

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

總結(jié)

  • 分享了并發(fā)和并行
  • 分享了GO 的并發(fā),協(xié)程的簡單使用
  • 簡單分享了GO可伸縮擴(kuò)展的棧內(nèi)存

到此這篇關(guān)于瞅一眼就能學(xué)會(huì)的GO并發(fā)編程使用教程的文章就介紹到這了,更多相關(guān)GO并發(fā)編程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Golang中的路由使用詳解

    Golang中的路由使用詳解

    這篇文章主要介紹了Golang中的路由使用詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-06-06
  • 詳解如何使用Golang擴(kuò)展Envoy

    詳解如何使用Golang擴(kuò)展Envoy

    這篇文章主要為大家介紹了詳解如何使用Golang擴(kuò)展Envoy實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • Go gin框架處理panic的方法詳解

    Go gin框架處理panic的方法詳解

    本文我們介紹下recover在gin框架中的應(yīng)用, 首先,在golang中,如果在子協(xié)程中遇到了panic,那么主協(xié)程也會(huì)被終止,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • Go實(shí)踐反向代理ReverseProxy解析

    Go實(shí)踐反向代理ReverseProxy解析

    這篇文章主要為大家介紹了Go實(shí)踐反向代理示例ReverseProxy解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • Go語言驅(qū)動(dòng)低代碼應(yīng)用引擎工具Yao開發(fā)管理系統(tǒng)

    Go語言驅(qū)動(dòng)低代碼應(yīng)用引擎工具Yao開發(fā)管理系統(tǒng)

    這篇文章主要為大家介紹了Go語言驅(qū)動(dòng)低代碼應(yīng)用引擎工具Yao開發(fā)管理系統(tǒng)使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Go語言實(shí)現(xiàn)AES加密并編寫一個(gè)命令行應(yīng)用程序

    Go語言實(shí)現(xiàn)AES加密并編寫一個(gè)命令行應(yīng)用程序

    密碼學(xué)中的高級加密標(biāo)準(zhǔn)(Advanced Encryption Standard,AES),又稱Rijndael加密法,是經(jīng)常采用的一種區(qū)塊加密標(biāo)準(zhǔn)。本文就來用Go語言實(shí)現(xiàn)AES加密算法,需要的可以參考一下
    2023-02-02
  • 深入探究Golang中flag標(biāo)準(zhǔn)庫的使用

    深入探究Golang中flag標(biāo)準(zhǔn)庫的使用

    在本文中,我們將深入探討 flag 標(biāo)準(zhǔn)庫的實(shí)現(xiàn)原理和使用技巧,以幫助讀者更好地理解和掌握該庫的使用方法,文中的示例代碼講解詳細(xì),感興趣的可以了解一下
    2023-04-04
  • Go排序算法通用qsort函數(shù)使用示例

    Go排序算法通用qsort函數(shù)使用示例

    這篇文章主要為大家介紹了Go排序算法通用qsort函數(shù)使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • Golang中基礎(chǔ)的命令行模塊urfave/cli的用法說明

    Golang中基礎(chǔ)的命令行模塊urfave/cli的用法說明

    這篇文章主要介紹了Golang中基礎(chǔ)的命令行模塊urfave/cli的用法說明,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Golang并發(fā)讀取文件數(shù)據(jù)并寫入數(shù)據(jù)庫的項(xiàng)目實(shí)踐

    Golang并發(fā)讀取文件數(shù)據(jù)并寫入數(shù)據(jù)庫的項(xiàng)目實(shí)踐

    本文主要介紹了Golang并發(fā)讀取文件數(shù)據(jù)并寫入數(shù)據(jù)庫的項(xiàng)目實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06

最新評論