【问题标题】:should I use a channel or a sync.Mutex lock()?我应该使用通道还是 sync.Mutex lock()?
【发布时间】:2016-08-20 17:59:41
【问题描述】:

在执行go test -race 时,我发现在命令启动cmd.Start() 之前调用了os.Process.Kill,我提出了可能的解决方案,一个使用channel

package main

import "os/exec"

func main() {
    cmd := exec.Command("sleep", "10")
    started := make(chan struct{}, 1)

    go func() {
        <-started
        cmd.Process.Kill()
    }()

    if err := cmd.Start(); err != nil {
        panic(err)
    }
    started <- struct{}{}

    cmd.Wait()
}

或使用lock:

package main

import (
    "os/exec"
    "sync"
)

func main() {
    var lock sync.Mutex
    cmd := exec.Command("sleep", "10")

    lock.Lock()
    if err := cmd.Start(); err != nil {
        panic(err)
    }
    lock.Unlock()
    go func() {
        cmd.Process.Kill()
    }()

    cmd.Wait()
}

这两个选项都有效,但想知道什么是最惯用或更好的方法,而主要目标只是防止杀死尚未启动的进程。

【问题讨论】:

  • 两者都不应该使用,因为这是串行代码,完全不需要 goroutine。
  • @JimB 同意,不好的例子,但 AJPennster 的回答给了我一个很好的提示

标签: go mutex


【解决方案1】:

我建议你使用一个频道,但让我指出一些关于你的代码的事情。

我注意到您使用了缓冲通道,然后在调用使用该通道的 goroutine 之前先在该通道上发送数据。在我看来,最好是:

1) 使用无缓冲通道进行信令,尤其是在这种情况下。

2) 让 goroutine 负责启动进程并调用 wait,同时向 main 发出它已经启动的信号。

像这样:

package main

import "os/exec"

func main() {

    cmd := exec.Command("sleep", "10")
    started := make(chan struct{})

    go func(cmd *exec.Cmd, signal chan struct{}) {
        if err := cmd.Start(); err != nil {
            panic(err)
        }

        started <- struct{}{}
        cmd.Wait()
    }(cmd, started)

    <-started
    cmd.Process.Kill()
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-11
    • 2014-04-12
    • 1970-01-01
    • 1970-01-01
    • 2018-09-05
    • 1970-01-01
    • 1970-01-01
    • 2015-10-16
    相关资源
    最近更新 更多