簡體   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