真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

go語言并發(fā)編程

引言

說到go語言最厲害的是什么就不得不提到并發(fā),并發(fā)是什么?,與并發(fā)相關(guān)的并行又是什么?
并發(fā):同一時間段內(nèi)執(zhí)行多個任務(wù)
并行:同一時刻執(zhí)行多個任務(wù)

我們提供的服務(wù)有:成都網(wǎng)站建設(shè)、成都網(wǎng)站制作、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、紅山ssl等。為近1000家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的紅山網(wǎng)站制作公司

進(jìn)程、線程與協(xié)程

  • 進(jìn)程:
    進(jìn)程是具有一定獨(dú)立功能的程序關(guān)于某個數(shù)據(jù)集合上的一次運(yùn)行活動,進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個獨(dú)立單位。每個進(jìn)程都有自己的獨(dú)立內(nèi)存空間,不同進(jìn)程通過進(jìn)程間通信來通信。由于進(jìn)程比較重量,占據(jù)獨(dú)立的內(nèi)存,所以上下文進(jìn)程間的切換開銷(棧、寄存器、虛擬內(nèi)存、文件句柄等)比較大,但相對比較穩(wěn)定安全。
  • 線程:
    線程是進(jìn)程的一個實體,是CPU調(diào)度和分派的基本單位,它是比進(jìn)程更小的能獨(dú)立運(yùn)行的基本單位.線程自己基本上不擁有系統(tǒng)資源,只擁有一點(diǎn)在運(yùn)行中必不可少的資源(如程序計數(shù)器,一組寄存器和棧),但是它可與同屬一個進(jìn)程的其他的線程共享進(jìn)程所擁有的全部資源。線程間通信主要通過共享內(nèi)存,上下文切換很快,資源開銷較少,但相比進(jìn)程不夠穩(wěn)定容易丟失數(shù)據(jù)。
  • 協(xié)程:
    協(xié)程是一種用戶態(tài)的輕量級線程,協(xié)程的調(diào)度完全由用戶控制。協(xié)程擁有自己的寄存器上下文和棧。協(xié)程調(diào)度切換時,將寄存器上下文和棧保存到其他地方,在切回來的時候,恢復(fù)先前保存的寄存器上下文和棧,直接操作棧則基本沒有內(nèi)核切換的開銷,可以不加鎖的訪問全局變量,所以上下文的切換非常快。

goroutine

go語言原生支持并發(fā),可以用go關(guān)鍵字快速的讓一個函數(shù)創(chuàng)建為goroutine協(xié)程,也可以創(chuàng)建多個goroutine去執(zhí)行相同的函數(shù)。
sync.WaitGroup可以用來實現(xiàn)goroutine的同步
例如:

var wg sync.WaitGroup

func hello(i int) {
	defer wg.Done() // goroutine結(jié)束就-1
	fmt.Println("Hello Goroutine!", i)
}
func main() {

	for i := 0; i < 10; i++ {
		wg.Add(1) // 啟動一個goroutine就+1
		go hello(i)
	}
	wg.Wait() // 等待所有登記的goroutine都結(jié)束
}

最終打印出來的順序是亂序,因為goroutine是并發(fā)操作。
goroutine實際上就是go中的協(xié)程,在go語言中可以起成千上萬個goroutine協(xié)程來進(jìn)行并發(fā)編程

goroutine的調(diào)度

goroutine的調(diào)度基于GMP模型

  1. G代表一個goroutine對象,每次go調(diào)用的時候,都會創(chuàng)建一個G對象
  2. M代表一個線程,每次創(chuàng)建一個M的時候,都會有一個底層線程創(chuàng)建;所有的G任務(wù),最終還是在M上執(zhí)行
  3. P代表一個處理器,每一個運(yùn)行的M都必須綁定一個P,就像線程必須在么一個CPU核上執(zhí)行一樣

    P的個數(shù)就是GOMAXPROCS(最大256),啟動時固定的,一般不修改; M的個數(shù)和P的個數(shù)不一定一樣多(會有休眠的M或者不需要太多的M)(最大);每一個P保存著本地G任務(wù)隊列,也有一個全局G任務(wù)隊列;

并發(fā)安全

go原生提供并發(fā)原語goroutine和channel為構(gòu)造并發(fā)提供了一種優(yōu)雅而簡單的方式,go沒有顯示的利用鎖來控制并發(fā)安全,而是鼓勵提倡通過通信共享內(nèi)存而不是通過共享內(nèi)存而實現(xiàn)通信。

sync.atomic

Go語言中原子操作由內(nèi)置的標(biāo)準(zhǔn)庫sync/atomic提供。
這些功能需要非常小心才能正確使用。 除特殊的底層應(yīng)用程序外,同步更適合使用channel或sync包的功能。 通過消息共享內(nèi)存; 不要通過共享內(nèi)存進(jìn)行通信。

Mutex

互斥鎖是一種常用的共享資源訪問的方法,它能夠保證同時只有一個goroutine可以訪問資源。Go語言中使用sync包的Mutex類型來實現(xiàn)互斥鎖。

go在1.8默認(rèn)使用自旋模式,當(dāng)試圖獲取已經(jīng)被持有的鎖時,如果本地隊列為空并且 P 的數(shù)量大于1,goroutine 將自旋幾次(用一個 P 旋轉(zhuǎn)會阻塞程序)。自旋后,goroutine park。在程序高頻使用鎖的情況下,它充當(dāng)了一個快速路徑。

go在1.9新增了Starving模式,當(dāng)自旋模式搶到鎖,表示有協(xié)程釋放了鎖,如果waiter>0,即有阻塞等待的協(xié)程,會釋放信號量來喚醒協(xié)程,當(dāng)協(xié)程被喚醒后,發(fā)現(xiàn)Locked=1,鎖又被搶占,則又會阻塞,但在阻塞前會判斷自上次阻塞到本次阻塞經(jīng)歷了多長時間,如果超過1ms的話,會將Mutex標(biāo)記為"饑餓"模式,然后再阻塞。當(dāng)被標(biāo)記為饑餓狀態(tài)時,unlock 方法會 handsoff 把鎖直接扔給第一個等待者。
在饑餓模式下,自旋也被停用,因為傳入的goroutines 將沒有機(jī)會獲取為下一個等待者保留的鎖。

RWMutex

互斥鎖是完全互斥的,但是有很多場景下讀多寫少,因此我們并發(fā)去讀取一個資源而不涉及到資源修改的時候是完全沒必要加鎖的,這種情況下讀寫鎖是一種更好的選擇。
讀寫鎖分為讀鎖和寫鎖,讀鎖與讀鎖兼容,讀鎖與寫鎖互斥,寫鎖與寫鎖互斥。

errgroup

ErrGroup是 Go 官方提供的一個同步擴(kuò)展庫??梢詫⒁粋€大任務(wù)拆分成幾個小任務(wù)并發(fā)執(zhí)行,提高程序效率。sync.ErrGroup在sync.WaitGroup功能的基礎(chǔ)上,增加了錯誤傳遞,以及在發(fā)生不可恢復(fù)的錯誤時取消整個goroutine集合,或者等待超時

sync.pool

go語言為了降低GC壓力引入了sync.Pool對象池用來保存和復(fù)用臨時對象。sync.Pool是可伸縮的,并發(fā)安全的。其大小僅受限于內(nèi)存的大小。sync.pool對象池比較適合用來存儲一些臨時切狀態(tài)無關(guān)的數(shù)據(jù),但是不適合用來做連接池,因為存入對象池中的值有可能會在垃圾回收時被刪除掉
在go的1.13版本中引入了victim cache,會將pool內(nèi)數(shù)據(jù)拷貝一份,避免GC將其清空,即使沒有引用的內(nèi)容也可以保留最多兩輪GC.

channel

channel是一種類型安全的消息隊列,用以充當(dāng)兩個goroutine之間的消息通道。go語言的并發(fā)模型是CSP(Communicating Sequential Processes),提倡通過通信共享內(nèi)存而不是通過共享內(nèi)存而實現(xiàn)通信。
go語言中的channel是一種特殊的類型,遵循先入先出的規(guī)則,保證數(shù)據(jù)的收發(fā)順序。

無緩沖通道

//創(chuàng)建語法
ch := make(chan int)

無緩沖通道沒有容量,因此無緩沖的通道只有在有接收者的時候才能發(fā)送,否則會形成死鎖,相反如果接收操作先執(zhí)行,接收方的goroutine將阻塞,直到另一個goroutine在該通道上發(fā)送一個值。

func main() {
	ch := make(chan int)
	go func() {
		fmt.Println(<-ch)
	}()
	ch <- 10
}

無緩沖管道的本質(zhì)是為保證同步

有緩沖通道

//創(chuàng)建語法
ch := make(chan int, 10) //創(chuàng)建緩沖為10的通道

只要通道的容量大于零,那么該通道就是有緩沖的通道,通道的容量表示通道中能存放元素的數(shù)量,當(dāng)通道的容量已滿時將會阻塞發(fā)送者使其等待緩沖通道可用,而當(dāng)緩沖通道為空的時候會阻塞接收者使其等待資源被發(fā)送。
channel內(nèi)置的len函數(shù)可以獲取通道內(nèi)元素的數(shù)量,使用cap函數(shù)獲取通道的容量。

常見異常

References

https://www.cnblogs.com/lxmhhy/p/.html
https://blog.csdn.net/liangzhiyang/article/details/
https://www.cnblogs.com/sunsky303/p/.html
https://zhuanlan.zhihu.com/p/
https://zhuanlan.zhihu.com/p/
https://www.bilibili.com/read/cv/
https://pkg.go.dev/golang.org/x/sync/errgroup
https://mp.weixin.qq.com/s/NcrENqRyK9dYrOBBI0SGkA
https://www.jianshu.com/p/8fbbf6c012b2
https://www.jianshu.com/p/24ede9e
https://www.liwenzhou.com/posts/Go/14_concurrence/#autoid-1-4-3


名稱欄目:go語言并發(fā)編程
標(biāo)題鏈接:http://weahome.cn/article/dsoishg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部