Go sync.Cond是如何工作的?

Go sync.Cond是如何工作的?,go,Go,我正在尝试了解如何使用sync.Cond,但它对我不起作用。 我的代码 我总是会遇到死锁,但是如果我在wg.Done之前删除defer,则不会出现任何问题,但在这种情况下不会出现错误。我见过其他例子,但它们是不同的。我想用我的例子来理解sync.Cond的基本思想。我不知道这里哪里有错误,因为goroutine运行,然后它会等待信号,但在主goroutine中,我会执行此c.信号,因此我希望goroutine会继续,但不会发生…作为一般规则,1当您使用sync.Cond变量时,您需要两件事情:

我正在尝试了解如何使用sync.Cond,但它对我不起作用。 我的代码

我总是会遇到死锁,但是如果我在wg.Done之前删除defer,则不会出现任何问题,但在这种情况下不会出现错误。我见过其他例子,但它们是不同的。我想用我的例子来理解sync.Cond的基本思想。我不知道这里哪里有错误,因为goroutine运行,然后它会等待信号,但在主goroutine中,我会执行此c.信号,因此我希望goroutine会继续,但不会发生…

作为一般规则,1当您使用sync.Cond变量时,您需要两件事情:

互斥体,以及 互斥锁正在保护的数据结构。 在该数据结构中,您需要有一些变量来告诉您条件本身已满足或未满足

这将导致此表单的代码:

键入任意结构{ 准备好了吗 完蛋 输入字符串 结果字符串 锁同步 cond*sync.cond } func doStuffp*随便什么{ p、 锁,锁 延迟p.lock.Unlock 对于!p.ready&!p.done{ p、 康德,等等 } fmt.Printfworking对输入为%q的对象进行处理\n,p.input p、 结果=现在全部完成 p、 完成=正确 p、 条件信号 } func waitDonep*随便什么{ p、 锁,锁 延迟p.lock.Unlock 好了!p.好了{ p、 康德,等等 } } 然后从其他地方使用,例如:

var obj随便什么 obj.cond=sync.NewCond&obj.lock go doStuff&obj 锁 obj.input=某些输入 obj.ready=true//对象现在已准备好进行操作 锁定 目标秒信号 韦顿和欧比 fmt.Printfobj已完成,结果为%q\n,obj.result 这里有一个完整的例子

现在,如前所述,这里没有理由使用sync.Cond。在这种情况下,仅使用互斥就足够了。当多个并发例程需要等待某个事件时,我们实际上使用sync.Cond。例如,多个goroutine可能需要该对象:一个goroutine应该完成这项工作,然后它应该将该对象标记为就绪,并使用广播通知等待该对象的每个人。在这种情况下,doStuff将以p.cond.Broadcast而不是p.cond.Signal结束

在其他一些情况下,我们可能会有一个对象在不同的goroutine之间乒乓球。一个或多个goroutine正在或至少可能正在等待对象。其中一个让我们称之为这个特定的goroutine,Fred控制它并对对象做一些有限的工作,然后声明这个goroutine完成了。Fred将对象恢复到一个合适的状态,完成一些但不是所有的工作,并调用p.cond.Signal,这将唤醒所有正在等待对象的其他两个goroutin中的任何一个。无论哪一个被唤醒,都将接收该对象,对其进行更多的处理,然后将其恢复到合适的状态,并调用p.cond.Signal来向其他等待的人发出信号

最终,工作都完成了,完成工作的人设置p.done并调用p.cond.Broadcast来提醒所有可能掌握p的人p现在完成了

条件变量比简单的互斥锁更灵活,但需要更多的思考和注意。如果只使用一个简单的互斥体就可以完成任务,通常最好只使用互斥体


1有些情况下,您可能会违反此规则,但如果您准备好思考这些情况,您一开始就不会遇到此问题。你为什么在这里打电话给CLLOCK和CLUNLOCK?这就是导致死锁的原因-c.信号无法运行,因为它被锁定,c.L.Unlock无法运行,因为它在c.Wait之后运行,而c.Wait正在等待无法运行的c.信号。很抱歉,我的失败。。。但我该如何解决呢?见我之前的评论。解决这个问题的最快方法是停止干扰互斥锁,因为看起来你没有任何理由锁定和解锁它。@Adrian,需要锁定L:我很确定会发生死锁,因为主goroutine在等待有机会运行之前调用信号。在信号修复之前插入time.Sleeptime.Second:sync.Cond是通知组中的一个或所有服务员。我同意@Peter的说法,为什么这不起作用,但更重要的是,这段代码没有证明sync.Cond的有用性。
c := sync.NewCond(&sync.Mutex{})

var wg sync.WaitGroup
wg.Add(1)

go func() {
    defer wg.Done()
    c.L.Lock()
    defer c.L.Unlock()
    c.Wait()
    fmt.Println("I'm created")
}()

c.Signal()
wg.Wait()