2017-05-17 14 views
0

私はgolangには新しく、数値範囲と文字範囲の要素を組み合わせた10の英数字を印刷したいだけです。英数字を同時に印刷する際のデッドロックを回避する方法

私はそれを同時に行うことにしましたが、デッドロックに関するエラーが発生しました。

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()] 

} 

そして、それは正確に必要な番号を印刷した後にスローするエラーは次のとおりです。

❯ 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 

私は同時に、英数字の番号を印刷するにはデッドロックを回避するにはどうすればよいですか?

+0

サイドノートと同様に、生成されたすべての乱数に対して 'rand.Seed'を呼び出すことは間違いありません。 – hobbs

+0

@hobbsなので、DRYに違反しているだけでなく、パフォーマンスに大きな影響を及ぼしますか? –

+0

パフォーマンス上ではなく、正しさだけです。乱数のランダム化がはるかに少なくなります。 – hobbs

答えて

0

あなたの現在のコードはまったく並んでいません。すべての英数字コードは、main以外に、作成している単独のゴルーチン内で実行されている単一のforループで順次生成されます。

len(alphabets) == 26wg.Waitに追加しています。つまり、wg.Waitへの呼び出しに26 wg.Doneに電話する必要があります。各wg.Doneコールは、ウェイトグループカウンタを1減らします。

コードでは、wg.Doneを1回だけ呼び出しています。これは、ゴルーチンが返ってからwaitgroupカウンタが25にとどまり、wg.Doneをさらに呼び出すことによってwaitgroupカウンタを減らすことができる他のゴルーチンが実行されていないので、wg.Waitへの呼び出しが返されないことを意味します。

(漠然と)あなたは、あなたがこのような何か試すことができます欲しいものを得る:makeAlephを呼び出すことにより、一つのコードを印刷するための

// ... 

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() 

// ... 

さて、nゴルーチンが生み出される、それぞれの責任を。 goroutineが返されるとすぐに、wg.Doneが呼び出されます。合計nwg.Doneは、mainwg.Waitへのコールを許可すると呼ばれます。

+0

ありがとう@ abhink :) –

関連する問題