登录
首页 >  Golang >  Go问答

我如何检测死锁?

来源:stackoverflow

时间:2024-03-15 16:47:27 406浏览 收藏

**如何检测死锁** 在并行编程中,死锁是一种常见问题,它会导致程序无响应。本文将介绍如何检测死锁,并提供一些避免死锁的技巧。 死锁是指两个或多个线程无限期地等待对方释放资源。例如,线程 A 正在等待线程 B 释放锁,而线程 B 正在等待线程 A 释放锁。这会导致程序陷入僵局,无法继续执行。 为了检测死锁,我们可以使用一些工具,例如线程转储或死锁检测器。线程转储会显示所有正在运行的线程及其状态,而死锁检测器可以检测是否存在死锁的条件。

问题内容

我最近刚刚开始学习 go,想通过编写一个计算所有友好和完美数字的程序来测试我的技能。可悲的是我的代码有问题!如果有人知道在计算完所有数字后如何停止程序,最好没有错误,请告诉我。

package main

import (
    "fmt"
    "strings"
)

func getdivisorsum(number int) int {
    divisors := 0

    for possibledivisor := 1; possibledivisor <= number / 2; possibledivisor++ {
        if number % possibledivisor == 0 {
            divisors += possibledivisor
        }
    }

    return divisors
}

func checknumber(number int, channel chan string, done *int) {
    first := getdivisorsum(number)

    if first == number {
        channel <- fmt.sprintf("%d", number)
        *done += 1
        return
    }

    second := getdivisorsum(first)

    if number == second {
        channel <- fmt.sprintf("%d:%d", number, first)
        *done += 1
        return
    }
}

func checknumberrange(min int, max int) {
    channel := make(chan string)
    done := 0

    for number := min; number <= max; number++ {
        go checknumber(number, channel, &done)
    }

    for {
        tmp := <- channel

        if strings.contains(tmp, ":") {
            parts := strings.split(tmp, ":")
            fmt.printf("%s is an amicable of %s!\n", parts[0], parts[1])
        } else {
            fmt.printf("%s is perfect!\n", tmp)
        }
    }
}

func main() {
    checknumberrange(1, 65536)
}

目前程序因死锁而崩溃

tmp := <- channel

预先感谢,jooarye!


解决方案


您的程序存在多个问题:

  • done 的使用很活泼。多个 goroutine 在不同步的情况下写入它。看起来没有被使用过。
  • 您正尝试在无限 for 循环中读取通道。最终,当没有剩下的 goroutine 时,您会从通道中读取数据,这就是死锁。

解决这个问题的一种方法是使用sync.waitgroup,并以这种方式跟踪启动/停止 goroutine。

wg:=sync.waitgroup{}
for number := min; number <= max; number++ {
    wg.add(1)
    go checknumber(number, channel, &wg)
}

在支票号码中:

func checknumber(number int, channel chan string,wg *wg.waitgroup) {
  defer wg.done()
  ...
}

你可以有一个单独的 goroutine 来等待所有 goroutine 完成:

go func() {
  wg.wait()
  close(chan)
}()

并且,在 for 循环中,像这样读取它,以便它在通道关闭时终止:

for tmp:=range chan {
  ...
}

今天带大家了解了的相关知识,希望对你有所帮助;关于Golang的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>