与通道和 goroutine 同步
Posted
技术标签:
【中文标题】与通道和 goroutine 同步【英文标题】:Sync with channels and goroutines 【发布时间】:2013-05-21 17:34:26 【问题描述】:我正在尝试实施“工人”系统,但在确定它为什么会自行死锁时遇到了一些问题
代码通过调用fillQueue()来执行
我不明白为什么我的代码最终处于解除锁定状态(一个进程在“process()”的第二行等待,从通道“queue”读取,而另一个在“fillQueue”的末尾等待()" 等待从服务员那里读取。
我不明白为什么它从来没有得到服务员的阅读。
func process(queue chan *entry, waiters chan bool)
for
entry, ok := <-queue
if ok == false
break
fmt.Println("worker: " + entry.name)
entry.name = "whatever"
fmt.Println("worker finished")
waiters <- true
func fillQueue(q *myQueue)
// fill our queue
queue := make(chan *entry, len(q.pool))
for _, entry := range q.pool
fmt.Println("push entry")
queue <- entry
fmt.Printf("entry cap: %d\n", cap(queue))
// start the readers
var total_threads int
if q.maxConcurrent <= len(q.pool)
total_threads = q.maxConcurrent
else
total_threads = len(q.pool)
waiters := make(chan bool, total_threads)
fmt.Printf("waiters cap: %d\n", cap(waiters))
var threads int
for threads = 0; threads < total_threads; threads++
fmt.Println("start worker")
go process(queue, waiters)
fmt.Printf("threads started: %d\n", threads)
for ; threads > 0; threads--
fmt.Println("wait for thread")
ok := <-waiters
fmt.Printf("received thread end: %b\n", ok)
这是我运行时的日志:
push entry
push entry
push entry
entry cap: 3
waiters cap: 1
start worker
threads started: 1
wait for thread
worker: name1
worker: name2
worker: name3
throw: all goroutines are asleep - deadlock!
【问题讨论】:
广告“我不明白为什么它从来没有得到服务员的阅读。”:没有最低限度,但完整没有其他人可以理解i> 和可编译的代码。许多死锁纯粹是基于,例如,使用的缓冲通道与非缓冲通道。 【参考方案1】:简单回答:你需要关闭queue
。
只有当通道关闭时,双重接收运算符才会返回 false,而您永远不会这样做。所以进程中的循环永远不会退出。顺便说一句,您可以在通道上用 for/range 替换您的 for/if/break。
还有一些其他的围棋习语你应该考虑一下:你读过http://golang.org/doc/effective_go.html 吗?
【讨论】:
@djikstra 我几乎在您发布答案的同时发现了它......非常感谢!我以某种方式假设关闭通道意味着使其无法使用,而不仅仅是不再发生发送。是的,我正在阅读该页面(这是我的第一天去),但我更像是一个“做和被阻止”的学习者,所以在参观之后我开始给我分配一些东西来做例子学习。 没问题。我也倾向于以这种方式学习,只要确保你已经看过它:) 另一个技巧是在形式参数列表中标记通道结束,即func process(queue <-chan *entry, waiters chan<- bool)
,因为编译器可以告诉你你是否弄乱了它们的用法(在你的例子中你没有)。以上是关于与通道和 goroutine 同步的主要内容,如果未能解决你的问题,请参考以下文章
基本的 goroutine 和通道模式:一个通道的多个 goroutine
golang-----golang sync.WaitGroup解决goroutine同步