go - 如何在不使用 sync.WaitGroup 的情况下防止死锁?

标签 go concurrency channel

concurrent.go:

package main

import (
    "fmt"
    "sync"
)

// JOBS represents the number of jobs workers do
const JOBS = 2

// WORKERS represents the number of workers
const WORKERS = 5

func work(in <-chan int, out chan<- int, wg *sync.WaitGroup) {
    for n := range in {
        out <- n * n
    }
    wg.Done()
}

var wg sync.WaitGroup

func main() {
    in := make(chan int, JOBS)
    out := make(chan int, JOBS)

    for w := 1; w <= WORKERS; w++ {
        wg.Add(1)
        go work(in, out, &wg)
    }

    for j := 1; j <= JOBS; j++ {
        in <- j
    }
    close(in)

    wg.Wait()
    close(out)
    for r := range out {
        fmt.Println("result:", r)
    }

    // This is a solution but I want to do it with `range out`
    // and also without WaitGroups
    // for r := 1; r <= JOBS; r++ {
    //  fmt.Println("result:", <-out)
    // }
}

例子是 here在 goplay 上。

最佳答案

Goroutines 并发且独立运行。 Spec: Go statements:

A "go" statement starts the execution of a function call as an independent concurrent thread of control, or goroutine, within the same address space.

如果要使用for rangeout channel 接收值,那意味着out channel 只能关闭一次goroutines 已完成发送。

由于 goroutines 并发且独立运行,如果没有同步,您将无法实现这一点。

使用 WaitGroup 是一种方法,一种方法(以确保我们在关闭 out 之前等待所有 goroutine 完成它们的工作)。

您的注释代码是另一种方式:注释代码从 channel 接收的值与 goroutine 应该发送的值一样多,这只有在所有 goroutine 都发送它们的值时才有可能。同步是发送语句和接收操作。

注意事项:

通常从 channel 接收结果是异步完成的,在一个专用的 goroutine 中,或者甚至使用多个 goroutine。这样做,您不需要使用具有能够缓冲所有结果的缓冲区的 channel 。您仍然需要同步来等待所有工作人员完成他们的工作,由于 gorutine 调度和执行的并发和独立性质,您无法避免这种情况。

关于go - 如何在不使用 sync.WaitGroup 的情况下防止死锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44179480/

相关文章:

go - 基于字符串断言类型?

encryption - 三重 DES 解密返回错误的前 16 个字节再次解密时

json - 将map转换为json会在golang中给出很多整数

file - 当我加载文件并更改 MySpan 变量时如何写回 cfg 文件?

java - 在多线程中使用wait()和notify()

api - 从 channel 中找到一个YouTube用户ID

c# - tpl 数据流最大并行度

c++ - 等待往事

java NIO - 多线程访问 channel

go - 在 goroutine 中等待主线程 sleep