欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Golang中Channel的原理和使用技巧

 更新時間:2022年11月23日 08:59:21   作者:AllenWu  
Channel管道提供了一種機制,它在兩個并發(fā)執(zhí)行的協程之間進行同步,并通過傳遞與該管道元素類型相符的值來進行通信。本文主要介紹了Channel的原理和使用技巧,需要的可以參考一下

Channel 詳解

Channel 簡要說明

Channel(一般簡寫為 chan) 管道提供了一種機制,它在兩個并發(fā)執(zhí)行的協程之間進行同步,并通過傳遞與該管道元素類型相符的值來進行通信。Channel 是用來在不同的 goroutine 中交換數據的,千萬不要把 Channel 拿來在同一個 goroutine 中的不同函數之間間交換數據,chan 可以理解為一個管道或者先進先出的隊列。

Channel 類型定義

最簡單形式: chan elementType,通過這個類型的值,你可以發(fā)送和接收elementType 類型的元素。Channel 是引用類型,如果將一個 chan 變量賦值給另外一個,則這兩個變量訪問的是相同的 chann。

當然,我們可以用 make 分配一個channel:var c = make(chan int)

Channel 操作符<- 和操作方式

通信操作符 <- 的箭頭指示數據流向,箭頭指向哪里,數據就流向哪里,它是一個二元操作符,可以支持任意類型,對于 channel 的操作只有4種方式:

1.創(chuàng)建 channel (通過make()函數實現,包括無緩存 channel 和有緩存 channel);

2.向 channel 中添加數據(channel<-data);

3.從 channel 中讀取數據(data<-channel);

  • data<-channel, 從 channel 中接收數據并賦值給 data
  • <-channel,從 channel 中接收數據并丟棄

4.關閉 channel(通過 close()函數實現)

  • 讀取關閉后的無緩存通道,不管通道中是否有數據,返回值都為 0 和 false。
  • 讀取關閉后的有緩存通道,將緩存數據讀取完后,再讀取返回值為 0 和 false。
  • 對于一個關閉的 channel,如果繼續(xù)向 channel 發(fā)送數據,會引起 panic
  • channel 不能 close 兩次,多次 close 會 panic

Channel 有無緩沖 & 同步、異步

channel 分為有緩沖 channel 和無緩沖 channel,兩種 channel 的創(chuàng)建方法如下:

var ch = make(chan int) //無緩沖 channel,等同于make(chan int ,0),是一個同步的 Channel

  • 無緩沖 channel 在讀和寫的過程中是都會阻塞,由于阻塞的存在,所以使用 channel 時特別注意使用方法,防止死鎖和協程泄漏的產生。
  • 無緩沖 channel 的發(fā)送動作一直要到有一個接收者接收這個值才算完成,否則都是阻塞著的,也就是說,發(fā)送的數據需要被讀取后,發(fā)送才會完成
  • 一般要配合 select + timeout 處理,然后再在這里添加超時時間

var ch = make(chan int,10) //有緩沖channel,緩沖大小是10,是一個異步的Channel

  • 帶緩存的 channel 實際上是一個阻塞隊列。隊列滿時寫協程會阻塞,隊列空時讀協程阻塞。
  • 有緩沖的時候,寫操作是寫完之后直接返回的。相對于不帶緩存 channel,帶緩存 channel 不易造成死鎖。

Channel 各種操作導致阻塞和協程泄漏的場景

寫操作,什么時候會被阻塞?

1.向 nil 通道發(fā)送數據會被阻塞

2.向無緩沖 channel 寫數據,如果讀協程沒有準備好,會阻塞

  • 無緩沖 channel ,必須要有讀有寫,寫了數據之后,必須要讀出來,否則導致 channel 阻塞,從而使得協程阻塞而使得協程泄漏
  • 一個無緩沖 channel,如果每次來一個請求就開一個 go 協程往里面寫數據,但是一直沒有被讀取,那么就會導致這個 chan 一直阻塞,使得寫這個 chan 的 go 協程一直無法釋放從而協程泄漏。

3.向有緩沖 channel 寫數據,如果緩沖已滿,會阻塞

有緩沖的 channel,在緩沖 buffer 之內,不讀取也不會導致阻塞,當然也就不會使得協程泄漏,但是如果寫數據超過了 buffer 還沒有讀取,那么繼續(xù)寫的時候就會阻塞了。如果往有緩沖的 channel 寫了數據但是一直沒有讀取就直接退出協程的話,一樣會導致 channel 阻塞,從而使得協程阻塞并泄漏。

讀操作,什么時候會被阻塞?

  • 從 nil 通道接收數據會被阻塞
  • 從無緩沖 channel 讀數據,如果寫協程沒有準備好,會阻塞
  • 從有緩沖 channel 讀數據,如果緩沖為空,會阻塞

close 操作,什么時候會被阻塞?

close channel 對 channel 阻塞是沒有任何效果的,寫了數據但是不讀,直接 close,還是會阻塞的。

Channel 各種操作對應的狀態(tài)

  • 正常的 channel,可讀、可寫
  • nil 的 channel,表示未初始化的狀態(tài),只進行了聲明,或者手動賦值為 nil
  • 已經 closed 的 channel,表示已經 close 關閉了,千萬不要誤認為關閉 channel 后,channel 的值是 nil

Channel 長度和容量

容量(capacity)代表 Channel 容納的最多的元素的數量,代表Channel的緩存的大小。如果沒有設置容量,或者容量設置為0, 說明 Channel 沒有緩存,長度和容量的兩個函數是 cap 和 len 。

示例如下:

c := make(chan int, 100) // cap 就是 100,但是此時 len 為 0
c <- 0  // len = 1, cap = 100
c <- 0  // len = 2, cap = 100
<- c    // len = 1, cap = 100

Channel 的缺點

Channel 的缺點:

Channel 可能會導致循環(huán)阻塞或者協程泄漏,這個是最最最要重點關注的。

Channel 中傳遞指針會導致數據競態(tài)問題(data race/ race conditions)

Channel 中傳遞的都是數據的拷貝,可能會影響性能,但是就目前我們的機器性能來看,這點數據拷貝所帶來的 CPU 消耗,大多數的情況下可以忽略。

Go Channel 實現協程同步

channel 實現并發(fā)同步的說明

channel 作為 Go 并發(fā)模型的核心思想:不要通過共享內存來通信,而應該通過通信來共享內存,那么在 Go 里面,當然也可以很方便通過 channel 來實現協程的并發(fā)和同步了,并且 channel 本身還可以支持有緩沖和無緩沖的,通過 channel + timeout 實現并發(fā)協程之間的同步也是常見的一種使用姿勢。

無緩沖 chan 示例

示例如下:

package main
import "fmt"
func main() {
     var ch = make(chan string)
     for i := 0; i < 10; i++ {
             go sum(i, i+10, ch)
     }
     for i := 0; i < 10; i++ {
             fmt.Print(<-ch)
     }
}
func sum(start, end int, ch chan string) {
     var sum int = 0
     for i := start; i < end; i++ {
             sum += i
     }
     ch <- fmt.Sprintf("Sum from %d to %d is %d\n", start, end, sum)
}

有緩沖 chan 示例

	message_chan := make(chan int, 2)

	go func() {
		time.Sleep(time.Second * 3)
		println("start recv...")
		println(<-message_chan)
		println(<-message_chan)
		println(<-message_chan)
		println("finish recv...")
	}()

	println("start send 10...")
	message_chan <- 10

	println("start send 20...")
	message_chan <- 20

	println("start send 30...")
	message_chan <- 30

	println("finish send...")

	time.Sleep(time.Second * 3)
	close(message_chan)

到此這篇關于詳解Golang中Channel的原理和使用技巧的文章就介紹到這了,更多相關Golang Channel內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • golang?使用chromedp獲取頁面請求日志network

    golang?使用chromedp獲取頁面請求日志network

    這篇文章主要為大家介紹了golang?使用chromedp獲取頁面請求日志network方法實例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-11-11
  • golang關閉chan通道的方法示例

    golang關閉chan通道的方法示例

    在go語言中,通道(channel)是一個非常重要的概念,通道提供了一種在不同 goroutine 之間安全地傳遞數據的方式,在本文中,我們將討論如何關閉通道以及在關閉通道時需要考慮的事項,需要的朋友可以參考下
    2024-02-02
  • Go 互斥鎖和讀寫互斥鎖的實現

    Go 互斥鎖和讀寫互斥鎖的實現

    本文主要介紹了Go 互斥鎖和讀寫互斥鎖的實現,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • golang 語言中錯誤處理機制

    golang 語言中錯誤處理機制

    Golang 的錯誤處理方式可能和這些你熟悉的語言有所不同,今天通過本文給大家分享golang 語言中錯誤處理機制,感興趣的朋友一起看看吧
    2021-08-08
  • Go語言中如何通過方法為類型添加行為

    Go語言中如何通過方法為類型添加行為

    這篇文章主要介紹了Go語言中如何通過方法為類型添加行為的相關資料,文中通過圖文介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • 一文詳解Golang使用接口支持Apply方法的配置模式

    一文詳解Golang使用接口支持Apply方法的配置模式

    這篇文章主要為大家介紹了一文詳解Golang使用接口支持Apply方法的配置模式,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2024-01-01
  • go語言實現AES加密的方法

    go語言實現AES加密的方法

    這篇文章主要介紹了go語言實現AES加密的方法,實例分析了Go語言的加密技巧,需要的朋友可以參考下
    2015-03-03
  • 詳解在Go語言中如何實現枚舉類型

    詳解在Go語言中如何實現枚舉類型

    枚舉類型是一種常用的數據類型,用于表示一組有限的、預定義的、具名的常量值。而在?Go?語言里是沒有內置枚舉類型的,所以本文將介紹如何實現?“枚舉類型”,需要的可以參考一下
    2023-04-04
  • Golang調用FFmpeg轉換視頻流的實現

    Golang調用FFmpeg轉換視頻流的實現

    本文主要介紹了Golang調用FFmpeg轉換視頻流,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-02-02
  • go-zero熔斷機制組件Breaker接口定義使用解析

    go-zero熔斷機制組件Breaker接口定義使用解析

    這篇文章主要為大家介紹了go-zero熔斷機制組件Breaker接口定義使用解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-05-05

最新評論