channel是go的特色之一,甚至說是最大的特色也不為過,使用起來也非常簡單。
首先定義乙個int型別的channel:
我們這裡主要關注無緩衝通道。ch1 := make(chan
int) // 無緩衝通道
ch2 := make(chan
int,10) // 帶緩衝的通道
來看看這段**:
乍眼一看似乎沒毛病,但是當執行程式的時候:package main
import (
"sync"
"fmt"
)func main()
ch1 := make(chan
int)
wg.add(1)
for i :=0; i <10; i++
go func1(ch1, &wg)
wg.wait()
close(ch1)
fmt.println("close channel: ", ch1)
}func func1(ch chan
int, wg *sync.waitgroup) else
}default:
fmt.println("1 got nothing")}}
wg.done()
}
為什麼呢? 仔細看了看上面的程式,在定義了無緩衝通道ch1之後,立馬向其中寫入資料:fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/users/bruce/code/go/src/gocommonservices/sync-demo/demo.go:19 +0xb9
exit status 2
process finished with
exit code 1
但此時並沒有消費者,而無緩衝通道在寫入乙個資料之後,會等待消費者消費,程式阻塞,但啟動消費者的**:ch1 := make(chan int)
fori := 0; i
< 10; i++
go func1(ch1, &wg)
恰好在for迴圈之後,所以這個goroutine永遠沒有啟動的機會,這就是報錯資訊提示的,deadlock了,要修復這個有兩種方法:
1 ch1定義為緩衝通道,足夠容納for中的資料,就不會阻塞
2 先啟動消費者,再向通道中寫資料ch1 := make(chan
int,10)
歸根結底,還是因為channel的特性:go func1(ch1, &wg) // 先啟動消費者,再向ch1中寫入資料,以防阻塞
ch1 := make(chan
int)
for i :=0; i <10; i++
無緩衝的channel,不管是入還是出,都會阻塞,所以在同乙個goroutine中,不能同時對同乙個無緩衝channel進行入和出操作;channel無疑是go併發程式開發的利器,但使用的時候還是需要仔細慎重,注意避免像本文提到的這些『陷阱』。帶緩衝的channel,在佇列滿之前,不會阻塞;佇列滿之後,依然會阻塞。
Go 緩衝通道
語法結構 cap為容量 ch make chan type,cap 通道是非同步的,是一種在被建立時就被開闢了能儲存乙個或者多個值的通道。這種型別並不要求傳送與接收同時進行。只要緩衝區有未使用空間用於傳送資料,或還包含可以接收的資料,那麼其通訊就會無阻塞地進行。只有在通道中沒有要接收的值時,接收動作...
go語言通道插入0 Go語言帶緩衝的通道
go語言中有緩衝的通道 bufferedchannel 是一種在被接收前能儲存乙個或者多個值的通道。這種型別的通道並不強制要求goroutine之間必須同時完成傳送和接收。通道會阻塞傳送和接收動作的條件也會不同。只有在通道中沒有要接收的值時,接收動作才會阻塞。只有在通道沒有可用緩衝區容納被傳送的值時...
Go語言帶緩衝的通道實現
go語言中有緩衝的通道 buffered channel 是一種在被接收前能儲存乙個或者多個值的通道。這種型別的通道並不強制要求 goroutine 之間必須同時完成傳送和接收。通道會阻塞傳送和接收動作的條件也會不同。只有在通道中沒有要接收的值時,接收動作才會阻塞。只有在通道沒有可用緩衝區容納被傳送...