3 回答

TA貢獻(xiàn)1846條經(jīng)驗(yàn) 獲得超7個贊
在無緩沖通道中寫入通道不會發(fā)生,直到必須有一些接收器等待接收數(shù)據(jù),這意味著在下面的例子中
func main(){
ch := make(chan int)
ch <- 10 /* Main routine is Blocked, because there is no routine to receive the value */
<- ch
}
現(xiàn)在如果我們有其他 goroutine,同樣的原則適用
func main(){
ch :=make(chan int)
go task(ch)
ch <-10
}
func task(ch chan int){
<- ch
}
這將起作用,因?yàn)槿蝿?wù)例程正在等待數(shù)據(jù)被使用,然后寫入發(fā)生到無緩沖通道。
為了更清楚,讓我們交換主函數(shù)中第二條和第三條語句的順序。
func main(){
ch := make(chan int)
ch <- 10 /*Blocked: No routine is waiting for the data to be consumed from the channel */
go task(ch)
}
這會導(dǎo)致死鎖
所以簡而言之,只有當(dāng)有一些例程等待從通道讀取時才會寫入無緩沖通道,否則寫入操作將被永遠(yuǎn)阻塞并導(dǎo)致死鎖。
注意:相同的概念適用于緩沖通道,但在緩沖區(qū)已滿之前不會阻止發(fā)送方,這意味著接收方不一定要與每個寫操作同步。
因此,如果我們有大小為 1 的緩沖通道,那么您上面提到的代碼將起作用
func main(){
ch := make(chan int, 1) /*channel of size 1 */
ch <-10 /* Not blocked: can put the value in channel buffer */
<- ch
}
但是如果我們給上面的例子寫更多的值,那么就會發(fā)生死鎖
func main(){
ch := make(chan int, 1) /*channel Buffer size 1 */
ch <- 10
ch <- 20 /*Blocked: Because Buffer size is already full and no one is waiting to recieve the Data from channel */
<- ch
<- ch
}

TA貢獻(xiàn)1796條經(jīng)驗(yàn) 獲得超7個贊
在這個答案中,我將嘗試解釋錯誤消息,通過它我們可以稍微了解 go 在通道和 goroutines 方面的工作原理
第一個例子是:
package main
import "fmt"
func main() {
c := make(chan int)
c <- 1
fmt.Println(<-c)
}
錯誤信息是:
fatal error: all goroutines are asleep - deadlock!
在代碼中,根本沒有 goroutines(順便說一句,這個錯誤是在運(yùn)行時,而不是編譯時)。當(dāng) go 運(yùn)行此行時c <- 1,它希望確保通道中的消息將在某處(即<-c)收到。Go 不知道此時是否會收到頻道。因此,go 將等待正在運(yùn)行的 goroutine 完成,直到發(fā)生以下任一情況:
所有的 goroutine 都完成了(睡著了)
goroutine 之一嘗試接收通道
在第 1 種情況下,go 會出錯并顯示上面的消息,因?yàn)楝F(xiàn)在 go 知道 goroutine 無法接收通道并且它需要一個。
在第 2 種情況下,程序?qū)⒗^續(xù),因?yàn)楝F(xiàn)在知道收到了這個頻道。這解釋了 OP 示例中的成功案例。
- 3 回答
- 0 關(guān)注
- 253 瀏覽
添加回答
舉報