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