Go-并发编程-无缓冲和有缓冲 channel 的区别(二)

2023-04-21 13:49:38 浏览数 (1)

有缓冲 channel

有缓冲 channel 是指带有一定存储空间的 channel,发送和接收操作不一定需要同步进行。当缓冲区未满时,发送操作会立即返回,并将数据存储在缓冲区中,而接收操作则会等待直到缓冲区中有数据可用。当缓冲区已满时,发送操作将被阻塞,直到缓冲区中有空闲位置可用。

以下是使用有缓冲 channel 进行通信的例子:

代码语言:javascript复制
package main

import "fmt"

func main() {
    ch := make(chan int, 2)
    ch <- 1
    ch <- 2
    fmt.Println("receiving", <-ch)
    fmt.Println("receiving", <-ch)
}

在这个例子中,我们创建了一个带有 2 个存储空间的有缓冲 channel ch,然后向 channel 中发送了两个数值,并在主 goroutine无缓冲 channel 是指在 channel 中只能存储一个值,即该 channel 的容量为 0。如果有 goroutine 向一个未被接收的无缓冲 channel 中发送值,那么该 goroutine 会一直阻塞,直到有另一个 goroutine 从该 channel 中接收该值。这种阻塞的机制使得 goroutine 的执行是同步的,即发送和接收操作在 channel 上是同步的。

下面是一个使用无缓冲 channel 的例子:

代码语言:javascript复制
package main

import "fmt"

func main() {
    c := make(chan int) // 创建一个无缓冲 channel

    go func() {
        fmt.Println("Start goroutine")
        c <- 1 // 向 channel 发送值
        fmt.Println("End goroutine")
    }()

    fmt.Println("Start main")
    v := <-c // 从 channel 中接收值
    fmt.Println("Received", v)
    fmt.Println("End main")
}

输出结果为:

代码语言:javascript复制
Start main
Start goroutine
Received 1
End main
End goroutine

在 main 函数中,先创建了一个无缓冲 channel c,并启动了一个新的 goroutine,该 goroutine 向 channel 中发送了值 1。然后,main 函数中的代码从 channel 中接收值,并将其打印出来。在这个过程中,main 函数会一直阻塞,直到从 channel 中接收到值。接着,goroutine 中的代码继续执行,将打印出 End goroutine。

由于无缓冲 channel 在发送和接收操作上是同步的,因此在这个例子中,Start goroutine 和 Start main 的输出顺序是不确定的。因为无缓冲 channel 保证了发送和接收操作的同步,所以这个例子中的输出结果是正确的,而不会出现类似数据竞争的问题。

go

0 人点赞