中文字幕理论片,69视频免费在线观看,亚洲成人app,国产1级毛片,刘涛最大尺度戏视频,欧美亚洲美女视频,2021韩国美女仙女屋vip视频

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
一篇文章帶你了解Go語言基礎(chǔ)之并發(fā)(channel)
青山隱隱水迢迢, 秋盡江南草未凋。
前言
Hi,大家好,我是碼農(nóng),星期八,本篇繼續(xù)帶來Go語言并發(fā)基礎(chǔ),channel如何使用。
看看Go協(xié)程如何配合channel。
快來上車叭。
為什么需要channel
channel在Go中,也叫做管道,是用來多線程之間共享數(shù)據(jù)的。
通常情況下,在Go中共享數(shù)據(jù)用的也是channel,但是在Go有兩種共享數(shù)據(jù)方式。
共享內(nèi)存實現(xiàn)通訊。
通過管道(channel)通訊(推薦)。
為啥子共享內(nèi)存通訊不太推薦?
示例代碼:多線程修改一個值。
函數(shù)
func Calc() { defer wg.Done() NUM = NUM - 1}main
var NUM = 100var wg sync.WaitGroup
func main() { for i := 0; i<100;i++ { wg.Add(1) go Calc()} wg.Wait() fmt.Println(NUM)}執(zhí)行結(jié)果
沒錯,是2,懵了吧,哈哈哈,理論應(yīng)該是0才對呀。
這是為啥?
這就是共享內(nèi)存不太推薦的原因,我們的代碼已經(jīng)是多線程了。
在第一個函數(shù)代碼中,第3行,NUM = NUM - 1。
如果多個線程同時執(zhí)行到這一行,并且沒有加鎖,就會出現(xiàn)數(shù)據(jù)錯亂。
那該怎么做呢?
加鎖,加鎖可以保證某一段代碼只能被一個線程執(zhí)行,防止被爭搶。
代碼
func Calc() { defer wg.Done() mutex.Lock() NUM = NUM - 1 mutex.Unlock()}第3行加鎖,第5行解鎖。
執(zhí)行結(jié)果
這次真的是0的,不管執(zhí)行幾次。
但是會發(fā)現(xiàn)一個問題,如果采用這種方式,需要常常注意競爭問題。
所以不是太推薦,需要考慮的比較多,并且各種加鎖會消耗性能。
channel語法
channel格式
var 變量名 chan 類型例如var x1 chan int //x1管道里面只能存int類型數(shù)據(jù)var x2 chan string //x2管道里面只能存字符串類型數(shù)據(jù)注意
定義管道時,chan int是一個整體,別搞錯了各位。
創(chuàng)建channel
創(chuàng)建channel,只能通過make創(chuàng)建。
格式
var 變量名 = make(chan 類型,[管道大小])示例var chan1 = make(chan int,10)//管道可以放10個int元素var chan2 = make(chan string,5)//管道可以放5個string元素channel操作
創(chuàng)建一個管道。
ch = make(chan int,10)channel是一個管道,就像一個管子。
所以可以像管子里面塞東西,并且能取東西,關(guān)閉管道就是這個管道不能用了,里面的值取完就打樣了。
像管子塞東西(發(fā)送)ch <- 666。
從管子取東西(接收)var x = <- ch。
關(guān)閉管子close(ch)。
注意:channel是先入先出結(jié)構(gòu),就像這樣。
注意事項:
如果通道塞滿了,再塞 會阻塞住。
如果通道關(guān)閉了,是不能再塞值了,否則會panic。
即使通道關(guān)閉了,依然可以取值,直到將管道的值取完,取完后得到的是對應(yīng)類型零值。
管道不能重復(fù)關(guān)閉,重復(fù)關(guān)閉會panic。
無緩沖管道
無緩沖就是這個管道沒有長度,就像這樣。
就像快讀員沒有快遞柜,需要直接將快遞給客戶,如果沒人要就撂攤子。
示例代碼
package main
import ( "fmt")
//模擬張三func 張三(x chan string) { var a = <-x fmt.Println(a)}
func main() { //通道沒有長度,就是無緩沖通道 var x = make(chan string) go 張三(x) x <- "張三的快遞" fmt.Println("張三快遞交付成功")}第16行寫入一個值,同理,張三就要等著去接,如果沒人接,那就完了。
假設(shè)注釋第9行代碼。
直接報錯,all goroutines are asleep - deadlock!,這句話的意思是所有的協(xié)程都睡著了,死鎖
無緩沖說明通道長度為0,發(fā)送一個值會阻塞住。
這就相當(dāng)于快遞員直接找張三,但是張三沒了,但是快遞員還得一直等著,等等等,然后掛了,終究還是沒送出去。
有緩沖管道
這個就簡單啦,多了一個快遞柜,快遞員直接將快遞仍快遞柜就行了。
示例代碼
package main
import ( "fmt" "sync")
var wg sync.WaitGroup
//快遞員,快遞員放10個快遞func 快遞員(kuaidigui chan string) { defer wg.Done() for i := 0; i < 10; i++ { fmt.Println("快遞員放入了第",i,"快遞") kuaidigui <- fmt.Sprintf("第%d個快遞", i)} //放完快遞就關(guān)閉了通道 close(kuaidigui)}
//張三,拿走3個快遞func 張三(kuaidigui chan string) { defer wg.Done() for i := 0; i < 3; i++ { fmt.Println("張三拿走" + <-kuaidigui)}}//李四拿走7個快遞func 李四(kuaidigui chan string) { defer wg.Done() for i := 0; i < 7; i++ { fmt.Println("李四拿走" + <-kuaidigui)}}func main() { //快遞柜,10個大小 var 快遞柜 = make(chan string, 10) wg.Add(3) go 快遞員(快遞柜) go 張三(快遞柜) go 李四(快遞柜) wg.Wait()}執(zhí)行結(jié)果
遍歷channel兩種方式
代碼
func main() { //快遞柜,10個大小 var ch = make(chan int, 10) //向管道中發(fā)送值 for i := 0; i < 10; i++ { ch <- i} //方式一取值 //for { //i, ok := <-ch ////取完值ok就是false //if !ok { // //結(jié)束循環(huán) // break //} //fmt.Println(i) //} //方式二取值 for i:=range ch{ fmt.Println(i)}}執(zhí)行結(jié)果
報錯是因為我在main中完成了發(fā)送值和取值兩個操作,所以會出現(xiàn)上述問題,但是結(jié)果是沒有錯的。
單向通道
我們知道通道是可以發(fā)送值和取值的,但是某些場景為了安全起見,理論來說只能取值,后者只能發(fā)送值。
單向通道通常只在函數(shù)參數(shù)中體現(xiàn)。
形參 chan<- chan類型只寫。
形參 <-chan chan類型只讀。
修改上述快遞員代碼。
package main
import ( "fmt" "sync")
var wg sync.WaitGroup
//快遞員,快遞員放10個快遞,只寫 chan<- stringfunc 快遞員(kuaidigui chan<- string) { defer wg.Done() for i := 0; i < 10; i++ { fmt.Println("快遞員放入了第", i, "快遞") kuaidigui <- fmt.Sprintf("第%d個快遞", i)} //放完快遞就關(guān)閉了通道 close(kuaidigui)}
//張三,拿走3個快遞,只讀<-chan stringfunc 張三(kuaidigui <-chan string) { defer wg.Done() for i := 0; i < 3; i++ { fmt.Println("張三拿走" + <-kuaidigui)}}
//李四拿走7個快遞func 李四(kuaidigui <-chan string) { defer wg.Done() for i := 0; i < 7; i++ { fmt.Println("李四拿走" + <-kuaidigui)}}func main() { //快遞柜,10個大小 var 快遞柜 = make(chan string, 10) wg.Add(3) go 快遞員(快遞柜) go 張三(快遞柜) go 李四(快遞柜) wg.Wait()}總結(jié)
上述講述了Go語言并發(fā)如何和channel配合使用,畢竟我們一般的任務(wù)都不是單獨運行的,都是互相配合的。
我們講述了如何創(chuàng)建channel,如何使用channel,有緩沖管道和無緩沖管道區(qū)別,并且拒了一個快遞員例子來展示協(xié)程和channel如何配合,最后用單向通道又加固了一下代碼。
我的代碼中使用了中文命名變量名是為了好看,實際開發(fā)中千萬不要這樣?。?!
上述代碼一定要敲一下,如果在操作過程中有任何問題,記得下面留言,我們看到會第一時間解決問題。
不積跬步無以至千里,不積小流無以成江海,給自己一個成長的時間
我是碼農(nóng)星期八,如果覺得還不錯,記得動手點贊一下哈。
感謝你的觀看。
如果你覺得文章還可以,記得點贊留言支持我們哈。感謝你的閱讀,有問題請記得在下方留言噢~
------------------- End -------------------
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
沒用過吧?!使用反射操作channel
?超強指南!Golang 并發(fā)編程
Go并發(fā)模式:管道和取消
goroutine和channel 如何控制并發(fā)順序?
Go:如何優(yōu)雅地實現(xiàn)并發(fā)編排任務(wù)
【譯】如何使用 Golang 中的 Go
更多類似文章 >>
生活服務(wù)
熱點新聞
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服