繁体   English   中英

在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例程的同时阻止其他go例程读取?

简单的回答:不。 放置在Go通道上的元素只能被读取一次,无论有多少goroutine试图同时读取该通道,并且无论通道是否被缓冲,该元素都适用。 除非一个元素多次发送到通道,否则不可能被两个不同的goroutine读取该元素。 关于通道语义,缓冲所做的唯一一件事就是消除了读写同步发生的必要性。

换句话说,不同的go例程可以在通道中捕获相同的元素,还是当一个go例程正在读取缓冲区时,另一个go例程已经读取并处理了某些元素?

不...

我相信非阻塞和线程安全概念之间的区别是一种误解。

非阻塞(缓冲)通道

仅在缓冲区已满时发送到缓冲的通道块。

缓冲通道 就像它所说的那样, 具有用于存储一些项目的缓冲区。 它允许读取goroutine在不等待写入的情况下进行读取goroutine在已将某些内容写入通道的情况下将项目放入通道。 如果通道没有缓冲,则只能包含单个项目,因此在撤回已写入的项目之前,它需要阻塞用于写入的通道。 “阻塞/非阻塞”概念与“线程安全”概念无关,非阻塞并不意味着不是线程安全的。

Go通道的线程安全

Go通道在所有可用的使用方式中都是线程安全的。 通道是一种引用类型,因此一旦分配了make通道,就可以按值传递,因为它具有指向单个内存插槽的隐式指针。 显然,频道项目中包含的内容永远不会被复制,并且无法被读取两次。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM