golang 中缓冲通道上的并发读取冲突?
Collision on concurrent read on buffered channel in golang?
我有一个被多个(在本例中为 4 个)go 例程读取的缓冲通道。
queue := make(chan string, 10000) // a large buffered channel
每个 go 例程检查通道中可用元素的数量并处理它们。
for i :=0; i< 4; i++{ // spun 4 go routines
go func() {
for {
for elem := range queue {
// do something with the elem from the channel
}
}
}
}
多个go例程在读取时会发生冲突吗?换句话说,不同的 go 例程是否可以在通道中获取相同的元素,或者当一个 go 例程正在读取缓冲区时,其他 go 例程已经读取并处理了一些元素?如何在一个go routine 正在读取时阻止其他go routines 读取?
简单的回答:没有。放置在 Go 通道上的元素只能被读取一次,无论有多少 goroutine 试图同时从通道读取,并且无论通道是否被缓冲都适用。一个元素不可能被两个不同的 goroutine 读取,除非该元素被多次 sent 到通道。就通道语义而言,缓冲所做的唯一一件事就是消除了读写同步发生的必要性。
In other words, could different go routine grab the same elem in the channel, or while one go routine is reading the buffer, the other go routines already read and processed some of the elements?
没有...
我认为非阻塞和线程安全概念之间存在误解。
非阻塞(缓冲)通道
Sends to a buffered channel block only when the buffer is full.
缓冲通道就像它说的那样有缓冲区来存储一定数量的项目。它允许读取 goroutine 无需等待写入 goroutine 就可以将项目放入通道,条件是某些内容已写入通道。如果一个通道没有缓冲,它只能包含一个项目,因此它需要在一个写入的项目被撤回之前阻塞通道进行写入。 "Blocking/non-blocking" 概念与 "thread safe" 概念无关,非阻塞并不意味着线程不安全。
Go 通道的线程安全
Go 通道在所有可用的使用方式中都是线程安全的。 Channel 是引用类型,因此一旦分配了 make
channel 就可以按值传递,因为它具有指向单个内存槽的隐式指针。显然包含在频道中的项目永远不会被复制,也无法被读取两次。
我有一个被多个(在本例中为 4 个)go 例程读取的缓冲通道。
queue := make(chan string, 10000) // a large buffered channel
每个 go 例程检查通道中可用元素的数量并处理它们。
for i :=0; i< 4; i++{ // spun 4 go routines
go func() {
for {
for elem := range queue {
// do something with the elem from the channel
}
}
}
}
多个go例程在读取时会发生冲突吗?换句话说,不同的 go 例程是否可以在通道中获取相同的元素,或者当一个 go 例程正在读取缓冲区时,其他 go 例程已经读取并处理了一些元素?如何在一个go routine 正在读取时阻止其他go routines 读取?
简单的回答:没有。放置在 Go 通道上的元素只能被读取一次,无论有多少 goroutine 试图同时从通道读取,并且无论通道是否被缓冲都适用。一个元素不可能被两个不同的 goroutine 读取,除非该元素被多次 sent 到通道。就通道语义而言,缓冲所做的唯一一件事就是消除了读写同步发生的必要性。
In other words, could different go routine grab the same elem in the channel, or while one go routine is reading the buffer, the other go routines already read and processed some of the elements?
没有...
我认为非阻塞和线程安全概念之间存在误解。
非阻塞(缓冲)通道
Sends to a buffered channel block only when the buffer is full.
缓冲通道就像它说的那样有缓冲区来存储一定数量的项目。它允许读取 goroutine 无需等待写入 goroutine 就可以将项目放入通道,条件是某些内容已写入通道。如果一个通道没有缓冲,它只能包含一个项目,因此它需要在一个写入的项目被撤回之前阻塞通道进行写入。 "Blocking/non-blocking" 概念与 "thread safe" 概念无关,非阻塞并不意味着线程不安全。
Go 通道的线程安全
Go 通道在所有可用的使用方式中都是线程安全的。 Channel 是引用类型,因此一旦分配了 make
channel 就可以按值传递,因为它具有指向单个内存槽的隐式指针。显然包含在频道中的项目永远不会被复制,也无法被读取两次。