我正在玩Goroutines和频道,想知道为什么标题出现错误。
我的想法是,我有一个全局int通道,每个路由都会增加它。
通过使用互斥锁,我希望通道可以按例程被锁定,但是失败了。
代码在这里:
package main
import (
"fmt"
"sync"
)
var number = make(chan int)
var mutex = &sync.Mutex{}
func worker(wg *sync.WaitGroup, id int) {
defer wg.Done()
mutex.Lock()
number <- id + <-number
mutex.Unlock()
}
func main() {
var wg sync.WaitGroup
number <- 0
for i := 0; i < 5; i++ {
wg.Add(1)
go worker(&wg, i)
}
wg.Wait()
fmt.Println(<-number) // expected output: 0+1+2+3+4 = 10
}
答案 0 :(得分:3)
这里的问题与您正在使用的通道有关,因为它没有缓冲。没有缓冲的通道将阻塞,直到有接收者接收消息为止。
在这里,主执行例程向通道添加了一个数字,然后创建了5个执行例程以既退出通道又添加到通道,然后等待它们完成,然后从通道中取出项目。直到有东西可以接收到该数字后,才能在该通道上添加0,以便在到达互斥体之前将其阻塞。
仅当有东西使通道脱离通道时,5 go例程才能完成。
如果通过向make调用提供大小来切换到缓冲的通道,则此操作将开始执行:
package main
import (
"fmt"
"sync"
)
var number = make(chan int, 5)
var mutex = &sync.Mutex{}
func worker(wg *sync.WaitGroup, id int) {
defer wg.Done()
mutex.Lock()
number <- id + <-number
mutex.Unlock()
}
func main() {
var wg sync.WaitGroup
number <- 0
for i := 0; i < 5; i++ {
wg.Add(1)
go worker(&wg, i)
}
wg.Wait()
fmt.Println(<-number) // expected output: 0+1+2+3+4 = 10
}
答案 1 :(得分:0)
Go中的通道用于在两个不同的goroutine之间进行同步。 goroutine将等待 read / write ,除非它找到另一个对同一通道进行 write / read 的goroutine(假定通道没有缓冲)
这意味着该程序将始终具有死锁:
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello, playground")
done := make(chan bool)
done <- true
<- done
}
因为第10行将被阻塞,以寻找从chan中读取的另一个goroutine,但是没有这样的goroutine。
因此,除非有其他goroutine从该通道读取/写入,否则从同一goroutine写入/读取将被阻止。