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() //新建一個協(xié)程, 新建一個任務(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)行,并在下次某個時(shí)候從該位置恢復(fù)執(zhí)行。
類似:接力賽,A跑了一會碰到代碼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")
}() //別忘了()
//特地寫一個死循環(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ù)量
先介紹一個最簡單的監(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"
)
//定義一個打印機(jī),參數(shù)為字符串,按每個字符打印
//打印機(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個協(xié)程,代表2個人,2個人同時(shí)使用打印機(jī)
go person1()
go person2()
//特地不讓主協(xié)程結(jié)束,死循環(huán)
for {
}
}通過channel解決資源競爭問題
package main
import (
"fmt"
"time"
)
//全局變量,創(chuàng)建一個channel
var ch = make(chan int)
//定義一個打印機(jī),參數(shù)為字符串,按每個字符打印
//打印機(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ù)他就會阻塞
Printer("world")
}
func main() {
//新建2個協(xié)程,代表2個人,2個人同時(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解決資源競爭的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
GO語言中創(chuàng)建切片的三種實(shí)現(xiàn)方式
這篇文章主要介紹了GO語言中創(chuàng)建切片的三種實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09
使用?gomonkey?Mock?函數(shù)及方法示例詳解
在 Golang 語言中,寫單元測試的時(shí)候,不可避免的會涉及到對其他函數(shù)及方法的 Mock,即在假設(shè)其他函數(shù)及方法響應(yīng)預(yù)期結(jié)果的同時(shí),校驗(yàn)被測函數(shù)的響應(yīng)是否符合預(yù)期,這篇文章主要介紹了使用?gomonkey?Mock?函數(shù)及方法,需要的朋友可以參考下2022-06-06
axios?gin的GET和POST請求實(shí)現(xiàn)示例
這篇文章主要為大家介紹了axios?gin的GET和POST請求實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04
go build -tags構(gòu)建約束試驗(yàn)示例解析
這篇文章主要為大家介紹了go build -tags構(gòu)建約束試驗(yàn)示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
Go并發(fā)編程中的錯誤恢復(fù)機(jī)制與代碼持續(xù)執(zhí)行實(shí)例探索
這篇文章主要為大家介紹了Go并發(fā)編程中的錯誤恢復(fù)機(jī)制與代碼持續(xù)執(zhí)行實(shí)例探索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01
Golang中實(shí)現(xiàn)簡單的Http Middleware
本文主要針對Golang的內(nèi)置庫 net/http 做了簡單的擴(kuò)展,實(shí)現(xiàn)簡單的Http Middleware,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07

