go14--並發concurrency,Goroutine ,channel
阿新 • • 發佈:2017-12-21
不一定 port 內容 取出 高並發 false 阻塞 通知 don
package main /** 並發concurrency 很多人都是沖著 Go 大肆宣揚的高並發而忍不住躍躍欲試,但其實從 源碼的解析來看,goroutine 只是由官方實現的超級“線程池”而已。 不過話說回來,每個實例 4-5KB 的棧內存占用和由於實現機制而大幅 減少的創建和銷毀開銷,是制造 Go 號稱的高並發的根本原因。另外, goroutine 的簡單易用,也在語言層面上給予了開發者巨大的便利。 並發不是並行: 並發切換時間片,單核是沒有並行的,只有一個線程,在並行則是直接利用 多核實現多線程的運行,多核是並行,有多個線程,但 Go 可以設置使用核數,以發揮多核計算機 的能力。 高並發:因為創建銷毀的很快,每一個占內存很小, Goroutine 奉行通過通信來共享內存,而不是共享內存來通信。*/ import ( "fmt" "runtime" "time" ) func main1() { go GO() //這就是一個Goroutine,運行了一個Goroutine, time.Sleep(2 * time.Second) //暫停2秒鐘,不暫停是不會輸出的GOGOGO的, } func GO() { fmt.Println("GOGOGO") } func main2() { c := make(chan bool) //創建一個channel go func() { //go後面接一個匿名函數 fmt.Println("GGGGGOOOOOO") c <- true //channel中存入true或false隨便, }() <-c //從channel中取出來,go啟動一個Goroutine之後main函數就執行到<-c並且阻塞了,因為他在等著從 //channel中取出東西來,只有c <- true執行了,放入東西到channel了,main就可以取出東西來了, //通知main函數,他那裏執行完畢了,main就繼續執行完了 } func main3() { c := make(chan bool) go func() { fmt.Println("GGGGGOOOOOO") c <- true //執行打印v,執行fmt.Println(v), close(c) //關閉不再叠代,不關閉則一直打印死鎖了 }() for v := range c { //叠代channel的時候,一直在等待有值進去,才可以取出來,在打印出來, fmt.Println(v) } /* GGGGGOOOOOO true */ } func main() { runtime.GOMAXPROCS(runtime.NumCPU()) //返回當前cpu的核數,並利用多核操作Goroutine(Goroutine是線程池) c := make(chan bool) for i := 0; i < 10; i++ { go GO1(c, i) //啟動9個goroutine } <-c //告訴main函數可以退出了 } func GO1(c chan bool, index int) { a := 1 for i := 0; i < 100000000; i++ { a += 1 } fmt.Println(index, a) if index == 9 { //啟動第九個goroutine的時候就可以告訴main函數可以退出了, //多核的時候index=9不一定是最後執行的,所以不一定會執行9遍,有可能執行一遍就退出了,解決方法:緩存的channel c <- true } }
package main import ( "fmt" "runtime" ) //緩存的channel func main() { runtime.GOMAXPROCS(runtime.NumCPU()) c := make(chan bool, 10) //緩存的channel,緩存10個, for i := 0; i < 10; i++ { go GO1(c, i) } for i := 0; i < 10; i++ { <-c //取10次,就知道goroutine執行完了,這樣就保證了能夠打印10 次 } } func GO1(c chan bool, index int) { a := 1 for i := 0; i < 100000000; i++ { a += 1 } fmt.Println(index, a) //,這樣就保證了能夠打印10 次 c <- true //存10次 } /* 9 100000001 5 100000001 0 100000001 8 100000001 7 100000001 4 100000001 1 100000001 2 100000001 6 100000001 3 100000001 */
package main import ( "fmt" "runtime" "sync" //有一個任務組,每完成一個任務就減一,等任務數為0的時候任務就完成了 ) //第二種解決方案:同步,通過同步包實現多個Goroutine 打印內容 func main() { runtime.GOMAXPROCS(runtime.NumCPU()) wg := sync.WaitGroup{} //創建一個任務組 wg.Add(10) //添加10個任務 for i := 0; i < 10; i++ { go GO1(&wg, i) //添加10個Goroutine } wg.Wait() //等待 } func GO1(wg *sync.WaitGroup, index int) { fmt.Println(index) //打印就是一次任務 wg.Done() //任務完成一次 } /* 0 9 1 2 3 4 5 6 7 8 */
go14--並發concurrency,Goroutine ,channel