我是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 :(得分:0)
您当前的代码根本不是并发的。除了for
之外,所有字母数字代码都是在您创建的唯一goroutine中运行的单个main
循环中按顺序生成。
您要将len(alphabets) == 26
添加到wg.Wait
。这意味着您需要致电26 wg.Done
来完成对wg.Wait
的调用。每次wg.Done
调用都会将等待组计数器减一。
在您的代码中,您只调用wg.Done
一次。这意味着一旦你的goroutine返回并且对wg.Wait
的调用永远不会返回,则waitgroup计数器将保持在25,因为没有其他goroutine正在运行,这可能会通过进一步调用wg.Done
来减少waitgroup计数器。
(模糊地)得到你想要的东西,你可以尝试这样的东西:
// ...
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都会通过调用makeAleph
来打印一个代码。一旦goroutine返回,就会调用wg.Done
。共调用n
wg.Done
个wg.Wait
,以便main
中的{{1}}完成调用。