心情记录:最近因为工作原因开始接触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。
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()
}
代码步骤解释(自己翻译的不准确):
c
;c
需要pool中的sudog
结构体来代表一个sender,这个结构体将代表这个goroutine和值foo;sendq
中;c
中读取消息;sendq
list出列来获得一个sender,即步骤3中说明的那个结构体;memmove
函数拷贝sender发送的值,打包到sudog
结构体中,给我们的变量去读取通道;sudog
。以下实例代码在刚才的基础上简单修改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.