Golang利用channel協(xié)調(diào)協(xié)程的方法詳解
前言
go 當(dāng)中的并發(fā)編程是通過(guò)goroutine來(lái)實(shí)現(xiàn)的,利用channel(管道)可以在協(xié)程之間傳遞數(shù)據(jù),實(shí)現(xiàn)協(xié)程的協(xié)調(diào)與同步。
使用
新建一個(gè)管道,使用make channel 來(lái)構(gòu)建
// 構(gòu)建一個(gè)緩存長(zhǎng)度為8 的管道 ch := make(chan int ,8) // 寫(xiě)入 ch <- 10 // 取出 number := <-ch // 關(guān)閉 close(ch)
注意: 取數(shù)據(jù)的時(shí)候,如果沒(méi)得取,會(huì)阻塞代碼的執(zhí)行,如果一直沒(méi)有取到,那就是死鎖
實(shí)現(xiàn)生產(chǎn)者消費(fèi)者模式
兩個(gè)生產(chǎn)者者協(xié)程和一個(gè)消費(fèi)者協(xié)程
使用waitGroup
func main() {
ch := make(chan int, 100)
wg := sync.WaitGroup{}
wg.Add(2)
// 生產(chǎn)者
go func() {
defer wg.Done()
// 寫(xiě)入數(shù)據(jù)
for i := 0; i < 10; i++ {
ch <- i
}
}()
// 生產(chǎn)者
go func() {
defer wg.Done()
// 寫(xiě)入數(shù)據(jù)
for i := 0; i < 10; i++ {
ch <- i
}
}()
wg2 := sync.WaitGroup{}
wg2.Add(1)
// 消費(fèi)者
go func() {
sum := 0
fmt.Printf("sum %d \n", sum)
for {
// 這里會(huì)等待
temp, ok := <-ch
// close 并且 管道為空,ok = false
if !ok {
break
} else {
sum += temp
}
}
fmt.Printf("sum %d \n", sum)
wg2.Done()
}()
// 等待倆生產(chǎn)者結(jié)束
wg.Wait()
// 生產(chǎn)數(shù)據(jù)之后,消費(fèi)者也并行讀完了,此時(shí)可以關(guān)閉 管道 來(lái) 跳出for循環(huán)了
close(ch)
// 等待消費(fèi)者協(xié)程結(jié)束
wg2.Wait()
}使用管道則將wg2相關(guān)的代碼改掉
func main() {
//...
//...
ch2 := make(chan struct{}, 0)
go func() {
sum := 0
fmt.Printf("sum %d \n", sum)
for {
// 這里會(huì)等待
temp, ok := <- ch
// close 并且 管道為空,ok = false
if !ok {
break
} else {
sum += temp
}
}
fmt.Printf("sum %d \n", sum)
ch2 <- struct{}{}
}()
// 等待倆生產(chǎn)者結(jié)束
wg.Wait()
// 關(guān)閉管道
close(ch)
// 等待消費(fèi)者協(xié)程結(jié)束
<-ch2
}實(shí)戰(zhàn)面試題: 「交替打印數(shù)字和字母」
題目
使用兩個(gè) goroutine 交替打印序列,一個(gè) goroutine 打印數(shù)字, 另外一個(gè) goroutine 打印字母, 最終效果如下:
12AB34CD56EF78GH910IJ1112KL1314MN1516OP1718QR1920ST2122UV2324WX2526YZ2728
解題思路
利用channel的 阻塞 來(lái)協(xié)調(diào)線(xiàn)程,達(dá)到線(xiàn)程交叉執(zhí)行的效果。
代碼
func main() {
letter, number := make(chan bool), make(chan bool)
wait := sync.WaitGroup{}
go func() {
i := 1
for {
if <-number {
fmt.Print(i)
i++
fmt.Print(i)
i++
letter <- true
}
}
}()
wait.Add(1)
go func() {
// 獲得ASCII碼
i := 'A'
for {
if <-letter {
// 當(dāng)前已經(jīng)超過(guò)Z時(shí),無(wú)需再打印
if i > 'Z' {
// 停止等待,并且跳出循環(huán)
wait.Done()
break
}
// 將ASCII碼強(qiáng)轉(zhuǎn)成字母輸出
fmt.Print(string(i))
i++
fmt.Print(string(i))
i++
number <- true
}
}
}()
// 放行數(shù)字打印的阻塞
number <- true
// 等待關(guān)閉主線(xiàn)程
wait.Wait()
}其實(shí)完全也可以將waitGroup換成管道
func main() {
letter, number := make(chan bool), make(chan bool)
// 再定義一個(gè)管道來(lái)等待,替代waitGroup的作用
wait := make(chan bool)
// 打印數(shù)字
go func() {
i := 1
for {
if <-number {
fmt.Print(i)
i++
fmt.Print(i)
i++
letter <- true
}
}
}()
// 打印字母
go func() {
// 獲得ASCII碼
i := 'A'
for {
if <-letter {
if i > 'Z' {
wait <- true
break
}
// 將ASCII碼強(qiáng)轉(zhuǎn)成字母輸出
fmt.Print(string(i))
i++
fmt.Print(string(i))
i++
number <- true
}
}
}()
number <- true
// 等待管道取值
<- wait
}到此這篇關(guān)于Golang利用channel協(xié)調(diào)協(xié)程的方法詳解的文章就介紹到這了,更多相關(guān)Golang channel協(xié)調(diào)協(xié)程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
golang用melody搭建輕量的websocket服務(wù)的示例代碼
在Go中,可以使用gin和melody庫(kù)來(lái)搭建一個(gè)輕量級(jí)的WebSocket服務(wù),gin是一個(gè)流行的Web框架,而melody是一個(gè)用于處理WebSocket的庫(kù),本文給大家演示如何使用gin和melody搭建WebSocket服務(wù),感興趣的朋友一起看看吧2023-10-10
go select編譯期的優(yōu)化處理邏輯使用場(chǎng)景分析
select 是 Go 中的一個(gè)控制結(jié)構(gòu),類(lèi)似于用于通信的 switch 語(yǔ)句。每個(gè) case 必須是一個(gè)通信操作,要么是發(fā)送要么是接收。接下來(lái)通過(guò)本文給大家介紹go select編譯期的優(yōu)化處理邏輯使用場(chǎng)景分析,感興趣的朋友一起看看吧2021-06-06
Golang實(shí)現(xiàn)AES對(duì)稱(chēng)加密算法實(shí)例詳解
所謂對(duì)稱(chēng)加密是指在加密和解碼時(shí)使用同一密鑰的加密方式,下面這篇文章主要給大家介紹了關(guān)于Golang實(shí)現(xiàn)AES對(duì)稱(chēng)加密算法的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02
Go?實(shí)現(xiàn)?WebSockets和什么是?WebSockets
這篇文章主要介紹了Go?實(shí)現(xiàn)?WebSockets和什么是?WebSockets,WebSockets?是構(gòu)建實(shí)時(shí)應(yīng)用程序的第一大解決方案,在線(xiàn)游戲、即時(shí)通訊、跟蹤應(yīng)用程序等,下文相關(guān)內(nèi)容介紹需要的小伙伴可以參考一下2022-04-04
詳解Go中g(shù)in框架如何實(shí)現(xiàn)帶顏色日志
當(dāng)我們?cè)诮K端上(比如Goland)運(yùn)行g(shù)in框架搭建的服務(wù)時(shí),會(huì)發(fā)現(xiàn)輸出的日志是可以帶顏色的,那這是如何實(shí)現(xiàn)的呢?本文就來(lái)和大家簡(jiǎn)單講講2023-04-04
GO使用阿里云,解決go get下載項(xiàng)目慢或無(wú)法下載的情況
這篇文章主要介紹了GO使用阿里云,解決go get下載項(xiàng)目慢或無(wú)法下載的情況,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
Golang實(shí)現(xiàn)Redis事務(wù)深入探究
這篇文章主要介紹了Golang實(shí)現(xiàn)Redis事務(wù)深入探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01

