2017-05-17 9 views
0

저는 golang을 처음 사용하기 때문에 numeber-range와 character-range의 요소를 결합한 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 외에도 작성중인 유일한 goroutine에서 실행되는 단일 for 루프에서 순차적으로 생성됩니다.

len(alphabets) == 26wg.Wait에 추가하고 있습니다. 즉, wg.Wait 전화를 받으려면 26 wg.Done으로 전화해야합니다. 각 wg.Done 호출은 대기 그룹 카운터를 1 줄입니다.

코드에서 wg.Done을 한 번만 호출합니다. 즉, goroutine이 돌아 오면 waitgroup 카운터가 25로 유지되고 wg.Done을 추가로 호출하여 대기 그룹 카운터를 줄일 수있는 다른 goroutine이 실행되지 않기 때문에 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 goroutines가 양산되고, 각각의 책임을. goroutine이 반환되자 마자 wg.Done이 호출됩니다. 총 nwg.Done을 호출하려면 wg.Waitmain에 전화를 허용합니다.

+0

고마워요 @ abhink :) –