求解释一个 Golang 并发 Chan 的问题
func Test_TarsSelect(t *testing.T) { trueCount := 0 falseCount := 0 for i := 0; i < 100000; i++ { if TarsThread() { trueCount++ } else { falseCount++ } } fmt.Println("trueCount:", trueCount) fmt.Println("falseCount:", falseCount) } func TarsThread() bool { someChan := make(chan bool) var gotChan bool go SomeFunc(someChan) select { //10 毫秒超时 case <-time.After(10 * time.Millisecond): case gotChan = <-someChan: } return gotChan } func SomeFunc(someChan chan bool) { //休眠 10 微秒 time.Sleep(10 * time.Microsecond) select { case someChan <- true: default: } }
如上所示的代码,在我这边执行 Test_TarsSelect
的结果是
=== RUN Test_TarsSelect trueCount: 99961 falseCount: 39
一般情况下会认为应该全部为 true
。
如何解释这种现象呢? golang 中所有并发的程序的先后性都是不保证的吗?
我认为解决办法是 someChan 初始化时,可以修改为缓冲区长度为 1 。
另外一个同事认为是将 SomeFunc
中的 default 逻辑去掉,改成 case <- time.After(time.MillionSecond * 10)
。
二者都可以解决问题,你们推荐使用哪一种,或者有更合理的解决办法吗?