当前位置:网站首页>Go language foundation ----- 16 ----- goroutine, GPM model
Go language foundation ----- 16 ----- goroutine, GPM model
2022-07-03 07:37:00 【Mango sauce】
1 How to use Goroutine
Precede a function or method call with a keyword go, You will also run a new Goroutine. for example :
// hi For a function
go hi()
2 The influence of abnormal exit of sub processes
When using sub processes, you must pay special attention to protecting each sub process , Ensure their normal and safe operation . Because the abnormal exit of the child coroutine will propagate the exception to the main coroutine , It will directly cause the main process to hang up , Then the whole program crashed .
for example :
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println("run in main goroutine")
go func() {
go func() {
defer fmt.Println(" Abnormal ")
fmt.Println("run in grand child goroutine")
var ptr *int
*ptr = 0x12345 // Deliberately creating a breakdown
fmt.Println("xx")
go func() {
fmt.Println("run in grand grand child goroutine")
}()
}()
time.Sleep(time.Second * 1) // Ensure that the above sub processes are completed , Otherwise, the program is parallel , May print first 222 end, Will affect the test .
fmt.Println("222 end")
}()
time.Sleep(time.Second * 3)
fmt.Println("main goroutine will quit")
}
It turns out that , It contains defer The statement's coroutine crashed , Led to his father's cooperation 、 All sub processes terminate , Finally, the program crashed .
3 Exception handling of coroutine -recover
As I said before recover It can catch exceptions , So we can use it to deal with the exception of the coroutine .
recover It's a Go Built in functions of language , You can let people who are in the process of downtime goroutine Come back ,recover Only in the delay function defer Effective in . If the current goroutine fall into panic, call recover You can capture panic The input value of , And resume normal execution .
// 1.3 Exception handling of coroutine -recover
package main
import (
"fmt"
"runtime"
)
// Context information to be passed in case of crash
type panicContext struct {
function string // Function where
}
// The protection mode allows a function
func ProtectRun(entry func()) {
// Deferred processing function
defer func() {
// In case of downtime , obtain panic Pass the context and print
err := recover()
if err != nil {
switch err.(type) {
case runtime.Error: // Runtime error
fmt.Println("runtime error:", err)
default: // Non runtime error
fmt.Println("error:", err)
}
} else {
fmt.Println("no error")
}
}()
// Execute function
entry()
}
func main() {
fmt.Println(" Before running ")
// 1. Allow a manually triggered error , Man made mistakes , The code is actually right .
ProtectRun(func() {
fmt.Println(" Before manual downtime ")
// Use panic Passing context
//a := &panicContext{" Manual trigger panic"}
//panic(a) // Pass it like this , Or it can be transmitted directly below
panic(&panicContext{
" Manual trigger panic"})
fmt.Println(" After manual downtime ")
})
// 2. Intentionally causing null pointer access error , The code is really wrong .
ProtectRun(func() {
fmt.Println(" Before the assignment goes down ")
var a *int
*a = 1
fmt.Println(" After the assignment goes down ")
})
fmt.Println(" After operation ") // See print here , The instructions use recover After the function , There's something wrong with the program , But it won't collapse .
}
It turns out that . Even if there is a code problem , The program won't crash , But as usual .
4 Start the million process
Go Language can manage millions of processes at the same time , Generally, millions of collaborative processes are started , Memory is probably used 4G-4.8G about , Corresponding to some servers with large memory , for example 128G, No problem at all .
// 1-4 Start the million process
package main
import (
"fmt"
"runtime"
"time"
)
const N = 1000000
func main() {
fmt.Println("run in main goroutine")
i := 1
for {
go func() {
// Every open collaboration is an endless cycle , Sleep together 1s Prevent occupation CPU Cause the computer to jam .
for {
time.Sleep(time.Second)
}
}()
if i%10000 == 0 {
fmt.Printf("%d goroutine started\n", i)
}
i++
if i == N {
break
}
}
fmt.Println("NumGoroutine:", runtime.NumGoroutine())
time.Sleep(time.Second * 15)
}
stay vscode test , Memory usage before execution 0.4G, Occupy after execution 4.8G, namely go Millions of collaborative processes occupy 4.4G about .

5 Dead cycle
If there is a dead cycle of individual processes, will it cause other processes to starve and not run ?
answer : It's not .
Test code :
package main
import (
"fmt"
"runtime"
"syscall"
"time"
)
// Get the thread ID, It's not a collaborative process ID
func GetCurrentThreadId() int {
var user32 *syscall.DLL
var GetCurrentThreadId *syscall.Proc
var err error
user32, err = syscall.LoadDLL("Kernel32.dll") // Windows With
if err != nil {
fmt.Printf("syscall.LoadDLL fail: %v\n", err.Error())
return 0
}
GetCurrentThreadId, err = user32.FindProc("GetCurrentThreadId")
if err != nil {
fmt.Printf("user32.FindProc fail: %v\n", err.Error())
return 0
}
var pid uintptr
pid, _, err = GetCurrentThreadId.Call()
return int(pid)
}
func main() {
//runtime.GOMAXPROCS: This function is used to set the maximum used by the current process cpu Count , The return value is the setting value of the last successful call , The first call returns the default value ( for example cpu by 4 Core, the return value is 4).
// runtime.GOMAXPROCS(1) // Set up CPU Concurrency is 1 nucleus .
fmt.Println("GOMAXPROCS:", runtime.GOMAXPROCS(0)) // Pass on 0 Represents using the default value
fmt.Println("run in main goroutine")
n := 5
for i := 0; i < n; i++ {
go func() {
fmt.Println("dead loop goroutine start, threadId:", GetCurrentThreadId())
for {
} // Dead cycle
fmt.Println("dead loop goroutine stop")
}()
}
go func() {
var count = 0
for {
time.Sleep(time.Second)
count++
fmt.Println("for goroutine running:", count, "threadId:", GetCurrentThreadId())
}
}()
fmt.Println("NumGoroutine: ", runtime.NumGoroutine()) // Print the number of coroutines that the current program is running , Here is 7. Because above for opened 5 individual , Again alone go One , Then add main This main process is 7 individual .
var count = 0
for {
time.Sleep(time.Second)
count++
fmt.Println("main goroutine running:", count, "threadId:", GetCurrentThreadId())
}
}
Take out part of the print to see , Even if there are some coroutines in dead cycle operation , But other processes can still be implemented .
See the thread of the loop ID It could be the same , This is because the same thread can have multiple coroutines .

6 Set the number of threads
Go Our scheduler uses a called GOMAXPROCS To determine how many threads of the operating system will execute at the same time Go Code for . The default value is CPU The number of core , So there is 8 When on a core machine , The scheduler will be in 8 individual OS Thread scheduling GO Code .
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println("runtime.NumCPU():", runtime.NumCPU()) // obtain CPU The maximum number of cores
// Read the default number of threads
fmt.Println(runtime.GOMAXPROCS(0))
// Set the number of threads to 10
runtime.GOMAXPROCS(10)
// Read the current number of threads
fmt.Println(runtime.GOMAXPROCS(0))
// Set the maximum cpu Count
runtime.GOMAXPROCS(runtime.NumCPU())
fmt.Println(runtime.GOMAXPROCS(0))
}
For example, this is my computer configuration , Note that different people may have different computer configurations , Result in different print results .
7 G-P-M Model
7.1 Why did you introduce synergy ?
The core reason is goroutine Lightweight of , From process to thread , Or from thread to coroutine , Its core is to make our scheduling unit more lightweight . You can easily create hundreds of thousands of goroutine Don't worry about running out of memory .
among :
- M Machine :os Threads ( That is, the threads provided by the operating system kernel ).
- G:goroutine, It contains the stack needed to schedule a coroutine and instruction pointer(IP Instruction pointer ) , And some other important scheduling information .
- P Process :M And P The intermediary of , Realization m:n The key of scheduling model ,M Must get P To be able to G To schedule ,P Actually, it's limited golang Scheduling its maximum concurrency . Represents a logical processor p Bind one os Threads .
7.2 system call 
- call system call( system call ) Enter the kernel without returning , To ensure the concurrency of scheduling ,golang The scheduler takes a thread from the thread pool or creates a new thread before entering the system call , At present P Give it to the new thread M1 perform .
- G0 After returning , Need to find an available P Continue operation , If not, put it in the global queue for scheduling .M0 stay G0 Exit or put back the thread pool after returning .
7.3 Workflow theft
- stay P On the queue goroutine After all scheduling , Corresponding M First of all, I will try from global runqueue In order to get goroutine To schedule . If golbal runqueue There is no goroutine, At present M From other sources M Corresponding P Of local runqueue Half of them goroutine Put in your own P Scheduling in .
In short, it is , Be your own thread P The scheduler does not goroutine when , From other threads P Get goroutine, This is workflow theft .
It depends on C The code went .
边栏推荐
- Analysis of the problems of the 10th Blue Bridge Cup single chip microcomputer provincial competition
- Responsive MySQL of vertx
- Common architectures of IO streams
- JS monitors empty objects and empty references
- 项目经验分享:实现一个昇思MindSpore 图层 IR 融合优化 pass
- Jeecg menu path display problem
- 技术干货|昇思MindSpore Lite1.5 特性发布,带来全新端侧AI体验
- Vertx's responsive redis client
- 技术干货|利用昇思MindSpore复现ICCV2021 Best Paper Swin Transformer
- 你开发数据API最快多长时间?我1分钟就足够了
猜你喜欢

Use of file class

Inverted chain disk storage in Lucene (pfordelta)

【开发笔记】基于机智云4G转接板GC211的设备上云APP控制

PAT甲级 1028 List Sorting

Application of pigeon nest principle in Lucene minshouldmatchsumscorer

Reconnaissance et détection d'images - Notes

Lucene introduces NFA

Partage de l'expérience du projet: mise en œuvre d'un pass optimisé pour la fusion IR de la couche mindstore

PAT甲级 1031 Hello World for U
![[coppeliasim4.3] C calls UR5 in the remoteapi control scenario](/img/ca/2f72ea3590c358a6c9884aaa1a1c33.png)
[coppeliasim4.3] C calls UR5 in the remoteapi control scenario
随机推荐
技术干货|AI框架动静态图统一的思考
UA camouflage, get and post in requests carry parameters to obtain JSON format content
Paper learning -- Study on the similarity of water level time series of Xingzi station in Poyang Lake
昇思MindSpore再升级,深度科学计算的极致创新
技术干货|利用昇思MindSpore复现ICCV2021 Best Paper Swin Transformer
截图工具Snipaste
JS monitors empty objects and empty references
【LeetCode】2. Valid Parentheses·有效的括号
Lucene introduces NFA
Mail sending of vertx
Project experience sharing: realize an IR Fusion optimization pass of Shengsi mindspire layer
PAT甲级 1027 Colors in Mars
Introduction of transformation flow
Qtip2 solves the problem of too many texts
Use of other streams
[Development Notes] cloud app control on device based on smart cloud 4G adapter gc211
Arduino 软串口通信 的几点体会
Technical dry goods | alphafold/ rosettafold open source reproduction (2) - alphafold process analysis and training Construction
Hisat2 - stringtie - deseq2 pipeline for bulk RNA seq
Lombok -- simplify code