日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

GO語言協程創建使用并通過channel解決資源競爭_Golang

作者:Jeff的技術棧 ? 更新時間: 2022-06-14 編程語言

創建協程

goroutine是go的設計核心,就是協程
主協程終止了,子協程也終止

package main
import (
	"fmt"
	"time"
)
func newTask() {
	for {
		fmt.Println("this is a newTask")
		time.Sleep(time.Second) //延時1s
	}
}
func main() {
	go newTask() //新建一個協程, 新建一個任務
	for {
		fmt.Println("this is a main goroutine")
		time.Sleep(time.Second) //延時1s
	}
}

主協程終止,子協程也終止

package main
import (
	"fmt"
	"time"
)
//主協程退出了,其它子協程也要跟著退出
func main() {
	go func() {
		i := 0
		for {
			i++
			fmt.Println("子協程 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時間片

等待其他協程執行完

runtime.Gosched()用于讓出CPU時間片,讓出當前goroutine(協程)的執行權限,調度器安排其他等待的任務運行,并在下次某個時候從該位置恢復執行。
類似:接力賽,A跑了一會碰到代碼runtime.Gosched()就把接力棒交給B,A歇著,B繼續跑

案例:

package main
import (
	"fmt"
	"runtime"
)
func main() {
	go func() {
		for i := 0; i < 5; i++ {
			fmt.Println("go")
		}
	}()
	for i := 0; i < 2; i++ {
		//讓出時間片,先讓別的協議執行,它執行完,再回來執行此協程
		runtime.Gosched() 
		fmt.Println("hello")
	}
}


go
go
go
go
go
hello
hello

Goexit立即結束當前協程

runtime.Goexit()  //立即結束當前協程

案例:

package main
import (
	"fmt"
	"runtime"
)
func test() {
	defer fmt.Println("ccccccccccccc")
	//return //終止此函數
	runtime.Goexit() //終止所在的協程
	fmt.Println("dddddddddddddddddddddd")
}
func main() {
	//創建新建的協程
	go func() {
		fmt.Println("aaaaaaaaaaaaaaaaaa")

		//調用了別的函數
		test()
		fmt.Println("bbbbbbbbbbbbbbbbbbb")
	}() //別忘了()
	//特地寫一個死循環,目的不讓主協程結束
	for {
	}
}
aaaaaaaaaaaaaaaaaa
ccccccccccccc

GOMAXPROCS設置并行CPU核數最大值,并返回之前的值

runtime.GOMAXPROCS() //設置并行CPU核數最大值,并返回之前的值
package main
import (
	"fmt"
	"runtime"
)
func main() {
	//n := runtime.GOMAXPROCS(1) //指定以1核運算
	n := runtime.GOMAXPROCS(2) //指定以8核運算
	fmt.Println("n = ", n)
	for {
		go fmt.Print(1)
		fmt.Print(0)
	}
}

runtime.NumGoroutine()獲取當前運行中的goroutine數量

先介紹一個最簡單的監控方式。

通過 runtime.NumGoroutine() 獲取當前運行中的 goroutine 數量,通過它確認是否發生泄漏。

func main() {
 go test()
 go test()
 go test()
 go test()
 a:=runtime.NumGoroutine()
 fmt.Println(a) // 5
 for  {
 }
}

多任務資源競爭問題

package main
import (
	"fmt"
	"time"
)
//定義一個打印機,參數為字符串,按每個字符打印
//打印機屬于公共資源
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個協程,代表2個人,2個人同時使用打印機
	go person1()
	go person2()
	//特地不讓主協程結束,死循環
	for {
	}
}

通過channel解決資源競爭問題

package main
import (
	"fmt"
	"time"
)
//全局變量,創建一個channel
var ch = make(chan int)
//定義一個打印機,參數為字符串,按每個字符打印
//打印機屬于公共資源
func Printer(str string) {
	for _, data := range str {
		fmt.Printf("%c", data)
		time.Sleep(time.Second)
	}
	fmt.Printf("\n")
}
//person1執行完后,才能到person2執行
func person1() {
	Printer("hello")
	ch <- 666 //給管道寫數據,發送
}
func person2() {
	<-ch //從管道取數據,接收,如果通道沒有數據他就會阻塞
	Printer("world")
}
func main() {
	//新建2個協程,代表2個人,2個人同時使用打印機
	go person1()
	go person2()
	//特地不讓主協程結束,死循環
	for {
	}
}

主協程如何等其余協程完再退出

var wg sync.WaitGroup
wg.Add(2)  //任務數
wg.Done() //結束
wg.Wait() //等待
package main
import (
	"fmt"
	"sync"
)
var wg sync.WaitGroup
func main() {
	wg.Add(2)
	out := producer()
	consumer(out)
	defer fmt.Println("主線程結束")
	wg.Wait()  //等待
}
//此通道只能寫,不能讀
func producer() chan interface{} {
	ch := make(chan interface{})
	go func() {
		for i := 0; i < 5; i++ {
			ch <- fmt.Sprintf("協程1-%d", i) //寫入字符串
		}
		defer close(ch)
		wg.Done()  //結束
	}()
	return ch
}
//此channel只能讀,不能寫
func consumer(data chan interface{}) {
	defer fmt.Println("讀取結束")
	go func() {
		for num := range data {
			fmt.Println(num)
		}
		wg.Done() //結束
	}()
}

原文鏈接:https://www.cnblogs.com/guyouyin123/p/13985447.html

欄目分類
最近更新