unbuffered and buffered channel in golang

心情記錄:最近因爲工作原因開始接觸golang,過年前掃了一遍。以前總是不那麼認真去記一些東西,總想着用的時候在去搜索查詢,但是這樣總是不熟練。
今年想努力向一個優秀的程序員/算法工程師靠攏,所以有空就記錄一下平時看到的技術點吧。

總述:

Effective Go 裏面指出:

If the channel is unbuffered, the sender blocks until the receiver
has received the value. If the channel has a buffer, the sender blocks
only until the value has been copied to the buffer; if the buffer is
full, this means waiting until some receiver has retrieved a value.
無緩衝通道即發送者一直阻塞直到接收者收到value;
緩衝通道即發送者只需阻塞直到value被拷貝到緩衝區,若緩衝區滿了,則等待直到某個接收者收到一個值。

以下例子來自參考1

1. 無緩衝通道

An unbuffered channel is a channel that needs a receiver as soon as a message is emitted to the channel.
無緩衝通道是消息一旦發送到該通道就需要接收者的通道。

package main

import (
	"sync"
	"time"
)

func main() {
	c := make(chan string)

	var wg sync.WaitGroup
	wg.Add(2)

	go func() {
		defer wg.Done()
		c <- `foo`
	}()

	go func() {
		defer wg.Done()

		time.Sleep(time.Second * 1)
		println(`Message: `+ <-c)
	}()

	wg.Wait()
}

代碼步驟解釋(自己翻譯的不準確):

  1. 創建一個空接收者和發送者列表的通道;
  2. line16:第一個goroutine發送值“foo”到通道 c
  3. 通道c需要pool中的sudog結構體來代表一個sender,這個結構體將代表這個goroutine和值foo;
  4. 現在將sender入隊到sendq中;
  5. 該goroutine的狀態變更爲waiting,變更原因爲“chan send”;
  6. line 23:第二個goroutine將從通道c中讀取消息;
  7. 通道使得sendqlist出列來獲得一個sender,即步驟3中說明的那個結構體;
  8. 該通道將用memmove函數拷貝sender發送的值,打包到sudog結構體中,給我們的變量去讀取通道;
  9. 至此,步驟5中中斷的goroutine現在重新開始,釋放步驟3中的sudog

2. 緩衝通道

以下實例代碼在剛纔的基礎上簡單修改c的buffer爲2:


package main

import (
	"sync"
	"time"
)

func main() {
	c := make(chan string, 2)

	var wg sync.WaitGroup
	wg.Add(2)

	go func() {
		defer wg.Done()

		c <- `foo`
		c <- `bar`
	}()

	go func() {
		defer wg.Done()

		time.Sleep(time.Second * 1)
		println(`Message: `+ <-c)
		println(`Message: `+ <-c)
	}()

	wg.Wait()
}

Goroutines spend 9ms blocked in synchronization waiting for a value from the unbuffered channel while a 50-sized buffer only wait for 1.9ms.
We do now have a confirmation of our previous doubts. The size of the buffer can play an important role in our application performances.

參考2

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章