简体   繁体   中英

Collision on concurrent read on buffered channel in golang?

I have a buffered channel that are read by multiple (4 in this example) go routines.

queue := make(chan string, 10000) // a large buffered channel

Each go routine checks the number of elements available in the channel and process them all.

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
            }
         }
     }
  }

Will multiple go routines collide on the reads? 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? How to block other go routines from reading while one go routine is reading?

Simple answer: no. Elements placed on a Go channel can only be read once, regardless of how many goroutines are trying to read off the channel at the same time, and that applies regardless of whether the channel is buffered or not. There's no possibility that an element will be read by two different goroutines unless that element was sent to the channel more than once. The only thing that buffering does, with regards to channel semantics, is remove the necessity for the read and write to occur synchronously.

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?

Nope...

I believe a misunderstanding is in difference between non-blocking and thread safe concepts.

Non blocking (buffered) channels

Sends to a buffered channel block only when the buffer is full.

Buffered channels just like it said have buffers to store some amount of items. It allows reading goroutine to read without await for writing goroutine put an item to a channel on condition something already written to a channel. If a channel unbuffered it can contain just single item therefore it requires to block channel for writing before a written item be withdrawn. "Blocking/non-blocking" concept doesn't related to "thread safe" concept and non-blocking doesn't mean not thread safe.

Thread safety of Go channels

Go channels are thread safe in all available ways of use. Channel is a reference type so once allocated with make channel could be passed by value because it has implicit pointer to a single memory slot. Obviously contained in a channel item never be copied and couldn't be read twice.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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