我只是在尝试golang。我遇到了一个有趣的结果。这是我的代码。
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
var str1, str2 string
wg.Add(2)
go func() {
fmt.Scanf("%s", &str1)
wg.Done()
}()
go func() {
fmt.Scanf("%s", &str2)
wg.Done()
}()
wg.Wait()
fmt.Printf("%s %s\n", str1, str2)
}
我提供了以下输入。
beat
it
我期待结果是
it beat
或
beat it
但我得到了。
eat bit
任何人都可以帮我弄明白为什么会这样吗?
答案 0 :(得分:4)
fmt.Scanf
不是原子操作。以下是实施:http://golang.org/src/pkg/fmt/scan.go#L1115
没有信号,没有什么能阻止两个并行执行。所以发生的只是执行是真正的并行,并且由于没有缓冲,任何字节读取都是IO操作,因此是调度程序改变goroutine的最佳时间。
答案 1 :(得分:3)
问题在于您在多个goroutine之间共享单个资源(stdin字节流)。
每个goroutine都可以在不同的非确定性时间产卵。即:
在大多数情况下,仅使用一个goroutine作为字节流来访问线性资源并将频道附加到它,然后产生多个听取该频道的消费者。
例如:
package main
import (
"fmt"
"io"
"sync"
)
func main() {
var wg sync.WaitGroup
words := make(chan string, 10)
wg.Add(1)
go func() {
for {
var buff string
_, err := fmt.Scanf("%s", &buff)
if err != nil {
if err != io.EOF {
fmt.Println("Error: ", err)
}
break
}
words <- buff
}
close(words)
wg.Done()
}()
// Multiple consumers
for i := 0; i < 5; i += 1 {
go func() {
for word := range words {
fmt.Printf("%s\n", word)
}
}()
}
wg.Wait()
}