MST

星途 面试题库

面试题:Go中带缓冲与无缓冲通道在数据发送和接收操作上的具体差异

请详细阐述在Go语言里,带缓冲通道和无缓冲通道在进行数据发送(send)和接收(receive)操作时,分别在什么情况下会阻塞,以及这种阻塞机制背后的原理。
21.8万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

无缓冲通道

  1. 发送操作阻塞情况:当无缓冲通道没有接收者时,发送操作会阻塞。例如:
package main

import (
    "fmt"
)

func main() {
    ch := make(chan int)
    ch <- 1 // 这里会阻塞,因为没有接收者
    fmt.Println("不会执行到这里")
}

原理:无缓冲通道要求发送和接收操作必须同时进行,它没有内部缓冲空间来暂存数据。发送方将数据发送到通道时,必须等待接收方准备好接收,否则发送操作就会阻塞在那里,直到有接收者从通道中取走数据。 2. 接收操作阻塞情况:当无缓冲通道没有数据发送进来时,接收操作会阻塞。例如:

package main

import (
    "fmt"
)

func main() {
    ch := make(chan int)
    go func() {
        ch <- 1
    }()
    value := <-ch // 这里如果没有上面的 goroutine 发送数据,会阻塞
    fmt.Println("接收到的值:", value)
}

原理:接收方尝试从通道接收数据时,如果通道中没有数据,接收操作就会阻塞,直到有数据发送到通道中。

带缓冲通道

  1. 发送操作阻塞情况:当带缓冲通道已满时,发送操作会阻塞。例如:
package main

import (
    "fmt"
)

func main() {
    ch := make(chan int, 2)
    ch <- 1
    ch <- 2
    ch <- 3 // 这里会阻塞,因为通道缓冲大小为2,已经满了
    fmt.Println("不会执行到这里")
}

原理:带缓冲通道有一定大小的内部缓冲区,可以暂存一定数量的数据。当缓冲区被填满后,再进行发送操作,由于没有额外的空间存储新数据,发送操作就会阻塞,直到有接收者从通道中取走数据,腾出空间。 2. 接收操作阻塞情况:当带缓冲通道为空时,接收操作会阻塞。例如:

package main

import (
    "fmt"
)

func main() {
    ch := make(chan int, 2)
    value := <-ch // 这里会阻塞,因为通道为空
    fmt.Println("接收到的值:", value)
}

原理:接收方尝试从通道接收数据时,如果通道中没有数据(缓冲区为空),接收操作就会阻塞,直到有数据发送到通道中。