1

我在使用 goroutines 时遇到了一些问题。为什么这段代码在 ~125ms 内执行(注意顺序执行):

package main

import (
  "os/exec"
  "time"
  "fmt"
)

func main() {
  cmd := exec.Command("lessc", "--yui-compress", "test.less")
  n := 2000
  start := time.Now()
  for i := 0; i < n; i++ {
    cmd.Run()
  }
  finish := time.Now()

  fmt.Printf("Program took %v to run\n", finish.Sub(start))
}

当这段代码大约需要 20 秒时(使用 goroutine 并发执行):

package main

import (
  "os/exec"
  "time"
  "fmt"
)

func main() {
  cmd := exec.Command("lessc", "--yui-compress", "test.less")
  ch := make(chan bool)
  n := 2000
  start := time.Now()
  for i := 0; i < n; i++ {
    go lessc(ch, cmd)
  }
  fmt.Println(n, " goroutines started.")
  for i := 0; i < n; i++ {
    _ = <-ch
  }
  finish := time.Now()

  fmt.Printf("Program took %v to run\n", finish.Sub(start))
}

func lessc(ch chan bool, c *exec.Cmd) {

  c.Run()
  ch <- true
}

在 i7 720QM (4C/8T) 8GB RAM linux/x86-64 上使用 go 1.0.3 也使用 1.0.2 构建和测试,在同一台机器上遇到了同样的问题。

编辑:由下面的@jnml 解决。如果有人关心这里的新固定并发代码,那就是:

package main

import (
  "os/exec"
  "time"
  "fmt"
)

func main() {
  ch := make(chan bool)
  n := 2000
  start := time.Now()
  for i := 0; i < n; i++ {
    go lessc(ch)
  }
  fmt.Println(n, " goroutines started.")
  for i := 0; i < n; i++ {
    _ = <-ch
  }
  finish := time.Now()

  fmt.Printf("Program took %v to run\n", finish.Sub(start))
}

func lessc(ch chan bool) {

  cmd := exec.Command("lessc", "--yui-compress", "test.less")
  cmd.Run()
  ch <- true
}
4

1 回答 1

11

IMO 你的程序不正确。它包含一个竞争条件,因此可以做任何事情。任何时间都没有意义。

您正在创建一个 exec.Cmd,然后同时(== 数据竞争)Run从多个 goroutine 执行其方法。exec.Cmd从来没有提到它可以被重复使用一次以上Run——即使是连续的。

exec.Cmd有一些由初始化的exec.Command状态和执行后的不同状态Run。IOW,执行该Run方法后,状态不再初始化,可能不适合另一个状态Run

于 2013-04-17T10:36:48.643 回答