[英]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通道在所有可用的使用方式中都是線程安全的。 通道是一種引用類型,因此一旦分配了make
通道,就可以按值傳遞,因為它具有指向單個內存插槽的隱式指針。 顯然,頻道項目中包含的內容永遠不會被復制,並且無法被讀取兩次。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.