[Go]通道(channel)的基本操作
通道類型是Go語言自帶的、唯一一個可以滿足并發安全性的類型,在聲明并初始化一個通道時,需要用到內建函數make,傳給make函數的第一個參數應該代表通道的具體類型的類型字面量。
如類型字面量 chan int,其中chan表示通道類型的關鍵字,而int說明了該通道類型的元素類型。
在初始化通道時,make函數除了必須接受這樣的字面量作為參數,還可以接收一個int類型的參數。后者是可選的,用于表示通道的容量(通道最多緩存多少個元素值),不能小于0。當容量為0時稱其為非緩沖通道,當容量大于0時,可以稱為緩沖通道
一個通道相當于一個先進先出(FIFO)的隊列。元素值的發送和接收都需要用到操作符? <-
1 package main 2 3 import "fmt" 4 5 func main() { 6 ch1 := make(chan int, 3) 7 ch1 <- 2 8 ch1 <- 1 9 ch1 <-3 10 elem1 := <-ch1 11 fmt.Printf("first element :%v\n", elem1) 12 }由于該通道容量為3,所以可以在通道不包含任何元素值的時候,連續地向該通道發送三個值,此時這三個值都會被緩存在通道之中。當從通道接收元素值的時候,同樣要用接送操作符 <-
?
1、對通道的發送和接收操作都有哪些基本的特性?
1)對于同一個通道,發送操作之間是互斥的,接收操作之間也是互斥的
在同一時刻,Go語言的運行時系統只會執行對同一個通道的任意個發送操作中的某一個,知道這個元素值被完全復制進該通道之后,其他針對該通道的發送操作才可能被執行
類似的,在同一時刻,運行時系統也只會執行對同一個通道的任意個接收操作中的某一個,直到這個元素值完全被移除該通道之后,其他針對該通道的接收操作才可能被執行。
另外,對于通道中的同一個元素值來說,發送操作和接收操作也是互斥的,雖會出現正在被復制進通道但還未復制完成的元素值,但此時它絕不會被想接收它的一方看到和取走
并且,元素值從外界進入通道時會被復制,進入通道的并不是接收操作符右邊那個元素值,而是它的副本。
?
2)發送操作和接收操作中對元素值的處理都是不可分割的
不可分割的意思是處理元素值時是一氣呵成不會被打斷的
發送操作要么還沒復制元素值,要么已經復制完畢,絕不會出現只復制一部分的情況
接收操作在準備好元素值的副本之后,一定會刪除通道中的原值,絕不會出現通道中仍有殘留的情況
對于通道中的桶一個元素值來說,它只可能是某一個發送操作放入的,同時也只可能被某一個接收操作取出
?
3)發送操作在完成之前會被阻塞,接收操作也是
發送操作包括“復制元素值”和“放置副本通道內部”兩個步驟,在這兩個步驟完全完成之前,發起這個發送操作的那句代碼會一直阻塞在那里,在它之后的代碼不會有執行的機會,直到這句代碼阻塞解除。在通道完成發送操作之后,運行時系統會通知這句代碼所在? ? ? ? ? ? ? ? ?的goroutine,以使它去爭取繼續運行代碼的機會
接收操作包括“復制通道內的元素”,“放置副本到接收方”,“刪掉原值”三個步驟,同理在這些步驟完全完成之前,發起該操作的代碼也會一直阻塞。
?
2、發送操作和接收操作在什么時候可能被長時間阻塞
1)緩沖通道
如果通道已滿,那么對它的所有發送操作都會被阻塞,直到通道中有元素值被接收走。通道會優先通知最早等待的那個發送操作所在的goroutine,通知的順序總是公平的
如果通道已空,那么對它的所以接收操作都會被阻塞,直到通道中有新的元素值出現,通道會優先通知最早等待的那個接收操作所在的goroutine,通知的順序總是公平的
2)非緩沖通道
無論發送操作還是接收操作,一開始執行就會被阻塞,直到配對的操作也開始執行。即非緩沖通道是在用同步的方式傳遞數據,也就是說,只有收發雙方對接上了,數據才會被床底,數據是直接從發送方復制到接收方的,中間并不會用非緩沖通道做中轉
3)對值為nil的通道
不論它的具體類型是什么,對它的發送操作和接收操作都會永久地處于阻塞狀態,它們所屬的goroutine中的任何代碼,都不會被執行。因此一定要初始化通道
?
3、發送操作和接收操作在什么時候會引發panic?
對于一個已初始化,但并未關閉的通道來說,收發操作一定不會引發panic,但通道一旦關閉,再對它進行發送操作,就會引發panic。
如果試圖關閉一個已經關閉了的通道,也會引發panic
當把接收表達式結果同時賦值給兩個變量時,第二個變量的類型就是一定bool類型,它的值如果是False就說明通道已經關閉,并且再沒有元素值可取。如果通道關閉時,里面還有元素值未被取出,那么接收表達式的第一個結果仍會是通道中的某一個元素值,而第二個結果值一定會是true
?
轉載于:https://www.cnblogs.com/yuxiaoba/p/9577212.html
總結
以上是生活随笔為你收集整理的[Go]通道(channel)的基本操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【DP优化】【P1430】序列取数
- 下一篇: VMware Workstation 1