duanfei8399 2017-05-17 06:33
浏览 19
已采纳

如何避免同时打印字母数字时出现死锁

I'm new to golang and I just wish to print out 10 alphanumeric numbers combining elements from numeber-range and character-range.

I decided to do it concurrently, but I've been running into an error regarding deadlock.

package main

import (
    "fmt"
    "math/rand"
    "sync"
    "time"
)

type alphanumeric struct {
    anAlphabet string
    aNumber    string
}

func (someStruct alphanumeric) pairAlphanumeric() string {

    return someStruct.aNumber + someStruct.anAlphabet

}

func main() {

    var wg sync.WaitGroup

    numbers := []string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"}
    alphabets := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}

    //var aleph alphanumeric
    //var alephS []alphanumeric

    wg.Add(len(alphabets))
    go func(numbers []string, alphabets []string) {
        defer wg.Done()
        for i := 0; i < 10; i++ {
            makeAleph(numbers, alphabets)
        }
    }(numbers, alphabets)

    wg.Wait()
} // end of main()

func makeAleph(numbers []string, alphabets []string) {

    var aleph alphanumeric

    aleph.anAlphabet = aNum(numbers)
    aleph.aNumber = anAlph(alphabets)

    fmt.Println(aleph.pairAlphanumeric())

    //return aleph.pairAlphanumeric()
}

func randomIndex() int {
    randTime := time.Time.UnixNano(time.Now())

    rand.Seed(randTime)

    return rand.Intn(10)
}

func aNum(numbers []string) string {

    return numbers[randomIndex()]

}

func anAlph(alphabets []string) string {

    return alphabets[randomIndex()]

}

And the error that it throws after printing the required numbers correctly is:

❯ go run aleph.go
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc42000e2dc)
    /Users/eklavya/.gvm/gos/go1.8/src/runtime/sema.go:47 +0x34
sync.(*WaitGroup).Wait(0xc42000e2d0)
    /Users/eklavya/.gvm/gos/go1.8/src/sync/waitgroup.go:131 +0x7a
main.main()
    /Users/eklavya/Projects/Polyglot/TedTalks/goTED/experiments/async/aleph.go:38 +0x14c

goroutine 5 [chan receive (nil chan)]:
main.makeAleph(0xc420084000, 0xa, 0xa, 0xc420001520, 0x1a, 0x1a)
    /Users/eklavya/Projects/Polyglot/TedTalks/goTED/experiments/async/aleph.go:61 +0x134
main.main.func1(0xc42000e2d0, 0xc420084000, 0xa, 0xa, 0xc420001520, 0x1a, 0x1a)
    /Users/eklavya/Projects/Polyglot/TedTalks/goTED/experiments/async/aleph.go:35 +0x94
created by main.main
    /Users/eklavya/Projects/Polyglot/TedTalks/goTED/experiments/async/aleph.go:37 +0x13e

goroutine 6 [chan send (nil chan)]:
main.aNum(0x0, 0xc420084000, 0xa, 0xa)
    /Users/eklavya/Projects/Polyglot/TedTalks/goTED/experiments/async/aleph.go:79 +0x5b
main.makeAleph.func1(0xc42000e2e0, 0x0, 0xc420084000, 0xa, 0xa)
    /Users/eklavya/Projects/Polyglot/TedTalks/goTED/experiments/async/aleph.go:51 +0x73
created by main.makeAleph
    /Users/eklavya/Projects/Polyglot/TedTalks/goTED/experiments/async/aleph.go:52 +0xad

goroutine 7 [chan send (nil chan)]:
main.anAlph(0x0, 0xc420001520, 0x1a, 0x1a)
    /Users/eklavya/Projects/Polyglot/TedTalks/goTED/experiments/async/aleph.go:85 +0x5b
main.makeAleph.func2(0xc42000e2e0, 0x0, 0xc420001520, 0x1a, 0x1a)
    /Users/eklavya/Projects/Polyglot/TedTalks/goTED/experiments/async/aleph.go:56 +0x73
created by main.makeAleph
    /Users/eklavya/Projects/Polyglot/TedTalks/goTED/experiments/async/aleph.go:57 +0xff
exit status 2

How can I avoid deadlock in printing alphanumeric numbers concurrently?

  • 写回答

1条回答 默认 最新

  • drox90250557 2017-05-17 06:51
    关注

    Your current code is not concurrent at all. All the alphanumeric codes are generated sequentially in a single for loop running in the sole goroutine you are creating besides main.

    You are adding len(alphabets) == 26 to wg.Wait. That means you need to call 26 wg.Done for the call to wg.Wait to complete. Each wg.Done call reduces the waitgroup counter by one.

    In your code, you are calling wg.Done only once. That means waitgroup counter stays at 25 once your goroutine returns and the call to wg.Wait would never return since no other goroutine is running that may reduce the waitgroup counter by making further calls to wg.Done.

    To (vaguely) get what you want, you can try something like this:

    // ...
    
    n := 10 // number of codes you want to print
    
    wg.Add(n)
    
    for i := 0; i < n; i++ {
      go func(numbers []string, alphabets []string) {
        defer wg.Done()
        makeAleph(numbers, alphabets)
      }(numbers, alphabets)
    
    wg.Wait()
    
    // ...
    

    Now, n goroutines will be spawned, each responsible for printing one code by calling makeAleph. As soon as a goroutine returns, wg.Done is called. A total n wg.Dones are called allowing call to wg.Wait in main to complete.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 delta降尺度计算的一些细节,有偿
  • ¥15 Arduino红外遥控代码有问题
  • ¥15 数值计算离散正交多项式
  • ¥30 数值计算均差系数编程
  • ¥15 redis-full-check比较 两个集群的数据出错
  • ¥15 Matlab编程问题
  • ¥15 训练的多模态特征融合模型准确度很低怎么办
  • ¥15 kylin启动报错log4j类冲突
  • ¥15 超声波模块测距控制点灯,灯的闪烁很不稳定,经过调试发现测的距离偏大
  • ¥15 import arcpy出现importing _arcgisscripting 找不到相关程序