2 回答

TA貢獻1796條經驗 獲得超7個贊
首先,你的兩個 goroutine 需要從chchannel 接收才能開始工作
for i<=10{
<-ch // wait until receive
fmt.Println(i)
i+=2
ch <- true
}
因此,您向通道發送一個值以ch使您的兩個 goroutine 工作
func main() {
//...
ch <- true
//...
}
但這不會按預期工作,因為您的兩個 goroutine 共享同一個ch通道。在執行時,它們ch <- true中main()只有一個可以接收、開始工作并將值發送回ch通道。
之后,兩個 goroutine 不斷從ch通道接收,開始工作并將值發送回通道
換句話說,兩個 goroutine 使用chchannel相互發送和接收值
for i<=10 {
<-ch // receive when main() executed at first time, after that receive from another goroutine
fmt.Println(i) // start work
i+=2 //
ch <- true // return back to the channel, another goroutine will receive it
}
wg.Done()
但是問題是當一個goroutine退出時,剩下的goroutine在工作后仍然嘗試發送到chchannel,但是沒有receiver,這會導致死鎖

TA貢獻1851條經驗 獲得超4個贊
如果通道中沒有空間,在通道上發送也會阻塞。如果您在通道中使用緩沖區,則發送可以工作。僅使用 1:
ch := make(chan bool, 1)
現在您可以發送數據了,它不會因為未滿而阻塞 go 例程。如果您再次發送而不讀取,那么它將阻止發送調用,因為再次沒有空間并且之前的值仍然沒有被消耗。
關于打印的順序: goroutine 將首先開始并沒有順序,go lang 規范沒有提到多個 goroutine 是否正在從一個通道接收數據,那么首先等待的是否真的首先得到它。因此,如果需要,您需要添加額外的同步來維護訂單。這是訂購同步的提示。
下面是修改后的打印代碼,但我更喜歡不同的方法。檢查上面鏈接中的 ping - pong 示例,其中使用了 2 個單獨的通道而不是一個。
package main
import (
"fmt"
"sync"
)
func odd(wg *sync.WaitGroup, ch chan bool) {
defer wg.Done()
i := 1
for i <= 10 {
<-ch
fmt.Println(i)
i += 2
ch <- true
}
}
func even(wg *sync.WaitGroup, ch chan bool) {
defer wg.Done()
i := 2
for i <= 10 {
<-ch
fmt.Println(i)
i += 2
ch <- true
}
}
func main() {
var wg sync.WaitGroup
ch := make(chan bool, 1)
defer close(ch)
wg.Add(2)
go even(&wg, ch)
go odd(&wg, ch)
ch <- true
wg.Wait()
}
- 2 回答
- 0 關注
- 97 瀏覽
添加回答
舉報