GO語言協(xié)程創(chuàng)建使用并通過channel解決資源競爭
創(chuàng)建協(xié)程
goroutine是go的設(shè)計(jì)核心,就是協(xié)程
主協(xié)程終止了,子協(xié)程也終止
package main import ( "fmt" "time" ) func newTask() { for { fmt.Println("this is a newTask") time.Sleep(time.Second) //延時(shí)1s } } func main() { go newTask() //新建一個(gè)協(xié)程, 新建一個(gè)任務(wù) for { fmt.Println("this is a main goroutine") time.Sleep(time.Second) //延時(shí)1s } }
主協(xié)程終止,子協(xié)程也終止
package main import ( "fmt" "time" ) //主協(xié)程退出了,其它子協(xié)程也要跟著退出 func main() { go func() { i := 0 for { i++ fmt.Println("子協(xié)程 i = ", i) time.Sleep(time.Second) } }() //別忘了() i := 0 for { i++ fmt.Println("main i = ", i) time.Sleep(time.Second) if i == 2 { break } } }
runtime包
Gosched讓出CPU時(shí)間片
等待其他協(xié)程執(zhí)行完
runtime.Gosched()用于讓出CPU時(shí)間片,讓出當(dāng)前goroutine(協(xié)程)的執(zhí)行權(quán)限,調(diào)度器安排其他等待的任務(wù)運(yùn)行,并在下次某個(gè)時(shí)候從該位置恢復(fù)執(zhí)行。
類似:接力賽,A跑了一會(huì)碰到代碼runtime.Gosched()就把接力棒交給B,A歇著,B繼續(xù)跑
案例:
package main import ( "fmt" "runtime" ) func main() { go func() { for i := 0; i < 5; i++ { fmt.Println("go") } }() for i := 0; i < 2; i++ { //讓出時(shí)間片,先讓別的協(xié)議執(zhí)行,它執(zhí)行完,再回來執(zhí)行此協(xié)程 runtime.Gosched() fmt.Println("hello") } } go go go go go hello hello
Goexit立即結(jié)束當(dāng)前協(xié)程
runtime.Goexit() //立即結(jié)束當(dāng)前協(xié)程
案例:
package main import ( "fmt" "runtime" ) func test() { defer fmt.Println("ccccccccccccc") //return //終止此函數(shù) runtime.Goexit() //終止所在的協(xié)程 fmt.Println("dddddddddddddddddddddd") } func main() { //創(chuàng)建新建的協(xié)程 go func() { fmt.Println("aaaaaaaaaaaaaaaaaa") //調(diào)用了別的函數(shù) test() fmt.Println("bbbbbbbbbbbbbbbbbbb") }() //別忘了() //特地寫一個(gè)死循環(huán),目的不讓主協(xié)程結(jié)束 for { } } aaaaaaaaaaaaaaaaaa ccccccccccccc
GOMAXPROCS設(shè)置并行CPU核數(shù)最大值,并返回之前的值
runtime.GOMAXPROCS() //設(shè)置并行CPU核數(shù)最大值,并返回之前的值
package main import ( "fmt" "runtime" ) func main() { //n := runtime.GOMAXPROCS(1) //指定以1核運(yùn)算 n := runtime.GOMAXPROCS(2) //指定以8核運(yùn)算 fmt.Println("n = ", n) for { go fmt.Print(1) fmt.Print(0) } }
runtime.NumGoroutine()獲取當(dāng)前運(yùn)行中的goroutine數(shù)量
先介紹一個(gè)最簡單的監(jiān)控方式。
通過 runtime.NumGoroutine() 獲取當(dāng)前運(yùn)行中的 goroutine 數(shù)量,通過它確認(rèn)是否發(fā)生泄漏。
func main() { go test() go test() go test() go test() a:=runtime.NumGoroutine() fmt.Println(a) // 5 for { } }
多任務(wù)資源競爭問題
package main import ( "fmt" "time" ) //定義一個(gè)打印機(jī),參數(shù)為字符串,按每個(gè)字符打印 //打印機(jī)屬于公共資源 func Printer(str string) { for _, data := range str { fmt.Printf("%c", data) time.Sleep(time.Second) } fmt.Printf("\n") } func person1() { Printer("hello") } func person2() { Printer("world") } func main() { //新建2個(gè)協(xié)程,代表2個(gè)人,2個(gè)人同時(shí)使用打印機(jī) go person1() go person2() //特地不讓主協(xié)程結(jié)束,死循環(huán) for { } }
通過channel解決資源競爭問題
package main import ( "fmt" "time" ) //全局變量,創(chuàng)建一個(gè)channel var ch = make(chan int) //定義一個(gè)打印機(jī),參數(shù)為字符串,按每個(gè)字符打印 //打印機(jī)屬于公共資源 func Printer(str string) { for _, data := range str { fmt.Printf("%c", data) time.Sleep(time.Second) } fmt.Printf("\n") } //person1執(zhí)行完后,才能到person2執(zhí)行 func person1() { Printer("hello") ch <- 666 //給管道寫數(shù)據(jù),發(fā)送 } func person2() { <-ch //從管道取數(shù)據(jù),接收,如果通道沒有數(shù)據(jù)他就會(huì)阻塞 Printer("world") } func main() { //新建2個(gè)協(xié)程,代表2個(gè)人,2個(gè)人同時(shí)使用打印機(jī) go person1() go person2() //特地不讓主協(xié)程結(jié)束,死循環(huán) for { } }
主協(xié)程如何等其余協(xié)程完再退出
var wg sync.WaitGroup wg.Add(2) //任務(wù)數(shù) wg.Done() //結(jié)束 wg.Wait() //等待 package main import ( "fmt" "sync" ) var wg sync.WaitGroup func main() { wg.Add(2) out := producer() consumer(out) defer fmt.Println("主線程結(jié)束") wg.Wait() //等待 } //此通道只能寫,不能讀 func producer() chan interface{} { ch := make(chan interface{}) go func() { for i := 0; i < 5; i++ { ch <- fmt.Sprintf("協(xié)程1-%d", i) //寫入字符串 } defer close(ch) wg.Done() //結(jié)束 }() return ch } //此channel只能讀,不能寫 func consumer(data chan interface{}) { defer fmt.Println("讀取結(jié)束") go func() { for num := range data { fmt.Println(num) } wg.Done() //結(jié)束 }() }
以上就是GO語言協(xié)程創(chuàng)建使用并通過channel解決資源競爭的詳細(xì)內(nèi)容,更多關(guān)于GO語言協(xié)程channel解決資源競爭的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解golang中?work與?module?的區(qū)別與聯(lián)系
Go?模塊通常由一個(gè)項(xiàng)目或庫組成,并包含一組隨后一起發(fā)布的?Go?包,Go?模塊通過允許用戶將項(xiàng)目代碼放在他們選擇的目錄中并為每個(gè)模塊指定依賴項(xiàng)的版本,解決了原始系統(tǒng)的許多問題,本文將給大家介紹一下golang中?work與?module?的區(qū)別與聯(lián)系,需要的朋友可以參考下2023-09-09基于Go語言實(shí)現(xiàn)一個(gè)并發(fā)下載器
這篇文章主要為大家詳細(xì)介紹了如何利用GO語言實(shí)現(xiàn)一個(gè)并發(fā)的文件下載器,可以在不重新啟動(dòng)整個(gè)下載的情況下處理錯(cuò)誤,感興趣的小伙伴可以了解一下2023-10-10golang文件服務(wù)器的兩種方式(可以訪問任何目錄)
這篇文章主要介紹了golang文件服務(wù)器的兩種方式,可以訪問任何目錄,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04golang實(shí)現(xiàn)簡易的分布式系統(tǒng)方法
這篇文章主要介紹了golang實(shí)現(xiàn)簡易的分布式系統(tǒng)方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-10-10Golang標(biāo)準(zhǔn)庫os/exec執(zhí)行外部命令并獲取其輸出包代碼示例
這篇文章主要為大家介紹了Golang標(biāo)準(zhǔn)庫os/exec執(zhí)行外部命令并獲取其輸出包代碼示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12Go事務(wù)中止時(shí)是否真的結(jié)束事務(wù)解析
這篇文章主要為大家介紹了Go事務(wù)中止時(shí)是否真的結(jié)束事務(wù)實(shí)例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04