1. 程式人生 > >Go goroutine

Go goroutine

idt ima 不支持 時區 min 如果 hello 兩個 cond

2018-07-25 16:40:10

goroutine

Go語言協程

技術分享圖片

定義

任何函數只需要加上go就能送給調度器運行

不需要在定義時區分是否是異步函數(這點是針對Python3.5引入的async def定義時說明自己是一個協程)

調度器在合適的點進行切換(非搶占式的,但切換點也不是任意的點,傳統是需要顯示寫出來,goroutine不需要)

可能切換的點:I/O,select ; channel ;等待鎖;函數調用(有時);runtime.Gosched()

註意:以上只是參考,不能保證切換,不能保證在其他地方不切換

使用-race來檢測數據訪問沖突

代碼

goroutine.go

package main

import (
	"fmt"
	"time"
)
//註意:兩個i都是i沒關系的  其余語言10/100個並發執行可以,但是1000個就很難啦
func main() {
	for i := 0; i < 1000; i++ {
		go func(i int) {  //開goroutine  這裏寫成一個匿名函數要方便點  
			for {
				fmt.Printf("Hello from goroutine %d\n", i) //Printf是一個io操作 由協程之間切換
			}
		}(i)
	}
	time.Sleep(time.Minute)//如果沒有這句話 是沒有輸出的 因為開了1000個goroutine還沒來得及輸出就完了  
}  

查看系統究竟起了多少個線程?
top命令查看:CPU 占用率 #TH線程(根據系統核來)

Coroutine協程

子程序是協程的一個特例

協程特點:

輕量級”線程”

非搶占式多任務處理,由協程主動交出控制權

編譯器/解釋器/虛擬機層面的多任務

多個協程可在一個或多個線程在工作

func main() {
    var a [10]int
   for i := 0; i<10 ; i++ {
      go func(i int) { //沒有i race condition
        for{
          a[i]++ //每個人都不斷的去做加法 沒有協程之間切換 沒辦法交出控制權
runtime.Gosched() //手動交出控制權 一般很少用 如果沒有這句,該例子程序會陷入死循環
        }
      }(i) //沒有i 會報錯 index out of range
  }
  time.Sleep(time.Millisecond)
  fmt.Println(a)
}  

普通函數與協程對比:doWork做完了才把控制權交給main

技術分享圖片

其他語言對協程支持

Go語言原生支持

C++:通過Boost.Coroutine庫支持

Java:不支持 (並不是完全不支持,有第三方的)

Python中:Python3.5以前使用yield關鍵字實現協程,Python3.5加入了async def 對協程原生支持

Go goroutine