通道竞争条件



这是关于通道的一个非常基本的问题。我已经读到发送时未缓冲的通道阻塞,那么为什么这段代码有一个竞争条件呢?

有时输出为

<- CREATE;
<- INSERT;
END
[CREATE; INSERT;]

有时候"INSERT;"在输出中丢失,但它被写入通道。

<- CREATE;
<- INSERT;
END
[CREATE; INSERT;]

如果阻塞了cmd := <-cSlit,SplitChan函数如何返回?

package main
import "fmt"
func main() {
batch := `CREATE;INSERT;`
res := Split(batch)
fmt.Print(res)
}
func SplitChan(batch string, outc chan<- string) {
b := 0
for i, c := range batch {
switch c {
case ';':
cmd := batch[b : i+1]
fmt.Println("<- " + cmd)
b = i + 1
outc <- cmd
}
}
fmt.Println("END")
}
func Split(batch string) []string {
var res []string
c := make(chan string)
go func() {
for {
cmd := <-c
res = append(res, cmd)
}
}()
SplitChan(batch, c)
close(c)
return res
}

游乐场链接:https://go.dev/play/p/WmO5OtmgETl

我期望每次运行都有相同的输出:

<- CREATE;
<- INSERT;
END
[CREATE; INSERT;]

我在这里错过了什么?谢谢你

SplitChan写入通道时,在例程中发生的追加操作和语句return res是并发的。return res可以看到包含一个元素或两个元素的切片。

你必须确保在返回之前,追加操作已经完成:

wg:=sync.WaitGroup{}
wg.Add(1)
go func() {
defer wg.Done()
for cmd :=  range c {
res = append(res, cmd)
}
}()
SplitChan(batch, c)
close(c)
wg.Wait()
return res

WaitGroup确保函数在执行完例程后返回。

最新更新