進程是內存資源管理和cpu調度的執行單元。為了有效利用多核處理器的優勢,將進程進一步細分,允許一個進程里存在多個線程,這多個線程還是共享同一片內存空間,但cpu調度的最小單元變成了線程。
那協程又是什么呢,以及與線程的差異性??
協程,可以看作是輕量級的線程。但與線程不同的是,線程的切換是由操作系統控制的,而協程的切換則是由用戶控制的。
最早支持協程的程序語言應該是lisp方言scheme里的continuation(續延),續延允許scheme保存任意函數調用的現場,保存起來并重新執行。Lua,C#,python等語言也有自己的協程實現。
Go中的goroutinue就是協程,可以實現并行,多個協程可以在多個處理器同時跑。而協程同一時刻只能在一個處理器上跑(可以把宿主語言想象成單線程的就好了)。 然而,多個goroutine之間的通信是通過channel,而協程的通信是通過yield和resume()操作。
goroutine非常簡單,只需要在函數的調用前面加關鍵字go即可,例如:
```
go elegance()
```
我們也可以啟動5個goroutines分別打印索引。
```
func main() {
for i:=1;i<5;i++ {
go func(i int) {
fmt.Println(i)
}(i)
}
// 停歇5s,保證打印全部結束
time.Sleep(5*time.Second)
}
```
在分析goroutine執行的隨機性和并發性,啟動了5個goroutine,再加上main函數的主goroutine,總共有6個goroutines。由于goroutine類似于”守護線程“,異步執行的,如果主goroutine不等待片刻,可能程序就沒有輸出打印了。
在Golang中channel則是goroutinues之間進行通信的渠道。
可以把channel形象比喻為工廠里的傳送帶,一頭的生產者goroutine往傳輸帶放東西,另一頭的消費者goroutinue則從輸送帶取東西。channel實際上是一個有類型的消息隊列,遵循先進先出的特點。
1. channel的操作符號
> `ch <- data`表示data被發送給`channel ch`;
> `data <- ch`表示從`channel ch`取一個值,然后賦給`data`。
2. 阻塞式channel
> `channel`默認是沒有緩沖區的,也就是說,通信是阻塞的。`send`操作必須等到有消費者`accept`才算完成。
應用實例:
```
func main() {
ch1 := make(chan int)
go pump(ch1) // pump hangs
fmt.Println(<-ch1) // prints only 1
}
func pump(ch chan int) {
for i:= 1; ; i++ {
ch <- i
}
}
```
在函數pump()里的channel在接受到第一個元素后就被阻塞了,直到主goroutinue取走了數據。最終channel阻塞在接受第二個元素,程序只打印 1。
沒有緩沖(buffer)的channel只能容納一個元素,而帶有緩沖(buffer)channel則可以非阻塞容納N個元素。發送數據到緩沖(buffer) channel不會被阻塞,除非channel已滿;同樣的,從緩沖(buffer) channel取數據也不會被阻塞,除非channel空了。
- 一、經典(一)
- 二、經典(二)
- 三、經典(三)
- 四、經典(四)
- 五、經典(五)
- 六、經典(六)
- 七、經典(七)
- 八、經典(八)
- 九、經典(九)
- 十、經典(十)
- 十一、經典(十一)
- 十二、經典(十二)
- 其他
- 1、知識點一
- 2、面試集
- 3、負載均衡原理
- 4、LVS相關了解
- 5、微服務架構
- 6、分布式鎖實現原理
- 7、Etcd怎么實現分布式鎖
- 8、Redis的數據結構有哪些,以及實現場景
- 9、Mysql高可用方案有哪些
- 10、Go語言的棧空間管理是怎么樣的
- 11、Goroutine和Channel的作用分別是什么
- 12、Go中的鎖有哪些?三種鎖,讀寫鎖,互斥鎖,還有map的安全的鎖?
- 13、怎么限制Goroutine的數量
- 14、Goroutine和線程的區別?
- 15、中間件原理