当前位置: 首页 > 面试题库 >

并发Go例程中的死锁错误

田鹤轩
2023-03-14
问题内容

我有三个并发的go例程,如下所示,

func Routine1() {
    mutex1.Lock()

    do something

    mutex2.Lock()
    mutex3.Lock()
    send int to routine 2
    send int to routine 3
   * Print Something *
    mutex2.Unlock()
    mutex3.Unlock()

    receive ints
    do something

    mutex2.Lock()
    mutex3.Lock()
    send int to routine 2
    send int to routine 3
    Print Something
    mutex2.Unlock()
    mutex3.Unlock()

    do something
    receive ints
    mutex1.Unlock()
    wg.Done()
}

func Routine2() {
    mutex2.Lock()

    do something

    mutex1.Lock()
    mutex3.Lock()
    send int to routine 1
    send int to routine 3
    Print Something
    mutex1.Unlock()
    mutex3.Unlock()

    do something
    receive ints

    mutex1.Lock()
    mutex3.Lock()
    send int to routine 1
    send int to routine 3
    Print Something
    mutex1.Unlock()
    mutex3.Unlock()

    do something
    receive ints
    mutex2.Unlock()
    wg.Done()
}

func Routine3() {
// same structure as routine 1 & 2
}
func main() {
wg.Add(3)
go Routine1()
go Routine2()
Routine3()
wg.Wait()
}

该逻辑代码每次都会出现死锁情况。实际上,当它运行时,只需多次执行例程1的打印语句(*标记之间的语句)(尽管我的打印语句只有一个)并给出死锁错误。有人可以告诉我代码逻辑有什么问题吗?谢谢。

注意
有关更多信息,请参见http://play.golang.org/p/pW6aXryUaK,此处仅执行行号290。包含错误的原始代码可以在play.golang.org/p/UL3rj8DJRk中找到。我只是向他们添加锁定和解锁。谢谢。

**我想补充一点:在play.golang.org/p/UL3rj8DJRk代码中,您可以找到各种打印语句的输出,如下所示:进程[number]在[时间纳秒]上将[int]发送到[number]到进程[number]
]。
但是,由于这三个并发例程的结果,有时print语句无法正确执行(意味着未完全打印,这是另一张打印插入的东西,例如进程[number]将[int]发送到进程[number]的进程[number]
])。谁能帮我解决这个问题?**


问题答案:

由于您发布的代码没有足够的信息,因此无法确定死锁的原因。

这可能是由于您获取锁的顺序引起的,也可能是由于使用了未缓冲的Go通道引起的。

在发布完整的Go源代码之前,您无法回答问题。

如果您需要讨论更长的代码,则可能应该将其发布到golang-nuts上。



 类似资料:
  • 主要内容:示例,死锁解决方案示例死锁描述了两个或多个线程等待彼此而被永久阻塞的情况。 当多个线程需要相同的锁定但以不同的顺序获取时,会发生死锁。 Java多线程程序可能会遇到死锁状况,因为关键字会导致执行线程在等待与指定对象相关联的锁定或监视时出现阻止情况。 看看下面一个例子。 示例 当您编译并执行上述程序时,会出现死锁情况,以下是程序生成的输出 - 上述程序将永久挂起,因为两个线程都不能继续进行,等待彼此释放锁定,所以您可以按

  • 问题内容: 由于以下代码中的某种原因,我收到“致命错误:所有goroutine都在睡眠-死锁!”。我正在使用应该不阻塞的缓冲通道。不知道我在做什么错 游乐场链接https://play.golang.org/p/J9meD5aKna 问题答案: 虽然您的解决方案可能会起作用,但我对此并不满意。 首先,您需要更改通道大小以使其起作用这一事实表明存在潜在的问题/错误。现在,每次您要启动另一个时,都必须

  • 本文向大家介绍C#中lock死锁实例教程,包括了C#中lock死锁实例教程的使用技巧和注意事项,需要的朋友参考一下 在c#中有个关键字lock,它的作用是锁定某一代码块,让同一时间只有一个线程访问该代码块,本文就来谈谈lock关键字的原理和其中应注意的几个问题: lock的使用原型是: 首先要明白为什么上面这段话能够锁定代码,其中的奥妙就是X这个对象,事实上X是任意一种引用类型,它在这儿起的作用就

  • 本文向大家介绍Java并发之嵌套管程锁死详解,包括了Java并发之嵌套管程锁死详解的使用技巧和注意事项,需要的朋友参考一下 ·嵌套管程死锁是如何发生的 ·具体的嵌套管程死锁的例子 ·嵌套管程死锁 vs 死锁 嵌套管程锁死类似于死锁, 下面是一个嵌套管程锁死的场景: 线程1获得A对象的锁。 线程1获得对象B的锁(同时持有对象A的锁)。 线程1决定等待另一个线程的信号再继续。 线程1调用B.wait(

  • 问题内容: 我有以下来自GoByExamples的并发渠道示例 Java中是否有等同的东西?我本以为实现同一件事会更加冗长。 问题答案: 语句 是 在Go中在语言语法级别引入并发的原因。并发函数调用可以(和通常完成)在库级别使用辅助函数(例如和通道)实现,就像在大多数其他语言中使用互斥或​​锁定的数据结构一样。但是声明不能。

  • 问题内容: 我不明白为什么这段代码中会发生死锁。我尝试了几种不同的方法来使僵局停止(使用WorkGroup的几种不同版本)。这是我在Go中的第一天,到目前为止,我对相当简单直接的操作的复杂性感到非常失望。我感觉好像缺少了一些明显的东西,但是我发现的所有文档似乎与对我来说是一种非常基本的操作模式都大不相同。所有文档都将原始类型用于通道(int,string),而不是更复杂的类型,所有类型都具有非常基