代码之家  ›  专栏  ›  技术社区  ›  Abe Miessler

与并发函数的结果不一致?

  •  -3
  • Abe Miessler  · 技术社区  · 6 年前

    我试图同时处理来自文件的行,但出于某种原因,我似乎得到了不一致的结果。我的代码的简化版本如下:

      var wg sync.WaitGroup
      semaphore := make(chan struct{}, 2)
      lengths:= []int{}
    
      for _, file := range(args[1:]){
        // Open the file and start reading it
        reader, err := os.Open(file)
        if err != nil {
          fmt.Println("Problem reading input file:", file)
          fmt.Println("Error:", err)
          os.Exit(0)
        }
        scanner := bufio.NewScanner(reader)
        // Start streaming lines
        for scanner.Scan() {
          wg.Add(1)
          text := scanner.Text()
          semaphore <- struct{}{}
          go func(line string) {
              length := getInformation(line)
              lengths = append(lengths, length)
              <-semaphore
              wg.Done()
          }(text)
        }
      }
      wg.Wait()
      sort.Ints(lengths)
      fmt.Println("Lengths:", lengths)
    

    这个 getInformation 函数只是返回行的长度。然后,我把这一行添加到一个数组中。我遇到的问题是,当我对同一个文件多次运行此命令时,在数组中会得到不同数量的项。从我使用 waitGroup 所有行都将每次处理,因此 lengths 会是一样的,但情况似乎并非如此。有人能看到我在这里做错了什么吗?

    1 回复  |  直到 6 年前
        1
  •  2
  •   superfell    6 年前

    这个 lengths = append(lengths, length) 正在同时执行。这是不安全的,并且会导致问题,如切片中缺少条目。您可以通过在互斥体中包装append调用来解决这个问题,或者让gorountine将结果发布到一个通道,并在一个地方将它们收集到一个切片中。