为什么在 goroutines 上没有 `.join` 操作?

Why is there no `.join` operation on goroutines?

为什么goroutines没有.join操作(即block until finished)操作?何时在主 goroutine 中进行而不是必须使用通道进行通信?

感觉好像我缺少有关 CSP 理论的一些基本知识。

编辑: 我问的是“为什么是这样”,而不是“我如何做到这一点”。

这仅仅是因为goroutines 不是线程。给定的 goroutine 可以由 Go 运行时调度以关联到操作系统线程,但是例如在阻塞 I/O 操作的情况下,所述线程可以关联到其他 goroutines 而另一个正在等待。

这是什么意思?

加入需要同步对象才能知道线程何时结束。由于 Go 的 goroutines 实际上只是一个非常轻量级的对象,只有一个栈,所以它们并没有直接提供这样的同步对象。

Go 的 CSP 前提是您可以非常便宜地实例化数千个 goroutine,并且只使用与物理 CPU 内核一样多的线程。 在 OS 的角度来看,同步对象是昂贵的,因此每个 goroutine 都有这样的对象是非常低效的。

相反,同步是通过使用同步包中的通道或 WaitGroup 实现的。

跟进

这是一个简单的示例,演示如何使用 sync.Mutex 执行此操作。我在这里选择 sync.Mutex 而不是 sync.WaitGroup 因为我只打算让每个 Thread 对象包装一个 goroutine,而 WaitGroups 旨在与多个 goroutines 一起使用。

type Thread struct {
    body func()
    mux sync.Mutex
}

func NewThread(body func ()) *Thread {
    return &Thread{
        body: body,
    }
}

func (thread *Thread) Start() {
    thread.mux.Lock()
    go thread.run()
}

func (thread *Thread) Join() {
    thread.mux.Lock()
    thread.mux.Unlock()
}

func (thread *Thread) run() {
    thread.body()
    thread.mux.Unlock()
}

您可以按如下方式使用它

func main() {
    t := NewThread(t1)
    t.Start()
    t.Join()
    print("Thread 1: Joined\n")
}

func t1() {
    print("Thread 1: Started\n")
    time.Sleep(5 * time.Second)
    print("Thread 1: Completed\n")
}