当前位置:网站首页>[go] runtime package for concurrent programming and its common methods

[go] runtime package for concurrent programming and its common methods

2022-06-24 16:19:00 Cabbage that wants to become powerful


One 、runtime package

1. runtime What is the bag for ?

My last article 【Go】 Concurrent programming Mentioned in ,Go Linguistic goroutine By Runtime (runtime) Scheduled and managed . In this article, we will introduce in detail runtime Knowledge of scheduler .

Even though Go The compiler produces locally executable code , This code still runs in Go Of runtime( This part of the code can be found in runtime Found in the package ) among .Go Linguistic runtime similar Java and .NET The virtual machine used by the language , It is responsible for management including memory allocation 、 Garbage collection ( The first 10.8 section )、 Stack processing 、goroutine、channel、 section (slice)、map And reflection (reflection) wait .

2. runtime Introduction to some methods in the package

runtime The scheduler is a very useful thing , About runtime Package several methods :

  1. Gosched(): Let the current thread give up cpu To let other threads run , It does not suspend the current thread , Therefore, the current thread will continue to execute in the future .

  2. NumCPU(): Returns the of the current system CPU Nuclear quantity .

  3. GOMAXPROCS(): Set the maximum number of simultaneous CPU Check the number .
    adopt runtime.GOMAXPROCS function , The application can set up... In the runtime system P The largest number . Be careful , If this value is set during operation , Can cause “Stop the World”. therefore , Should be called at the earliest stage of the application , And it's better to run Go Set the environment variables of the operating program before the program GOMAXPROCS, Instead of calling... In a program runtime.GOMAXPROCS function .
    No matter what the integer value we pass to the function is , Runtime system P The maximum value will always be 1~256 Between .
    go1.8 after , By default, let the program run on multiple cores , You don't have to set it .
    go1.8 front , Still need to set , Can make more efficient use of cpu.

  4. Goexit(): Quit current goroutine( however defer The statement will execute as usual ).

  5. NumGoroutine: Returns the total number of tasks in progress and queued .
    runtime.NumGoroutine Function after being called , Will return the in a specific state in the system Goroutine The number of . The specific state here refers to Grunnable\Gruning\Gsyscall\Gwaition. In these States Groutine That is, it is regarded as active or being scheduled .
    Be careful : Where the garbage is collected Groutine If the state of is also within this range , Will also be included in the counter .

  6. GOOS: View the target operating system . A lot of times , We will implement different operations according to different platforms , You can use it GOOS To view your operating system .

  7. runtime.GC: Will make the runtime system perform a mandatory garbage collection .
    Mandatory garbage collection : No matter what , All need to be garbage collected . Non mandatory garbage collection : Garbage collection will only be carried out under certain conditions ( The runtime , The unit of heap memory newly requested by the system since the last garbage collection ( Also known as unit increment ) The specified value is reached ).

  8. GOROOT() : obtain goroot Catalog .

  9. runtime.LockOSThread and runtime.UnlockOSThread function : The former call will make him call Goroutine With the currently running it M Locked together , The latter call will release such a lock .


Two 、runtime.Gosched()

Let go of the current arrangement CPU Time slice to other collaborators . The waiting time slice of the current collaboration process will continue to be executed in the future .

Release time slice , Let other processes execute first , It executes , And then come back to execute this process .

package main

import (
	"fmt"
	"runtime"
)

func main() {
    
	go func(s string) {
    
		for i := 0; i < 2; i++ {
    
			fmt.Println(s)
		}
	}("world")

	//  Main process 
	for i := 0; i < 2; i++ {
    
		runtime.Gosched()    // The main coordination process is released CPU Time slice , At this point, the above coordination process can be executed 
		fmt.Println("hello") //CPU Continue after the time slice returns 
	}
}

Output results :

hello
world
hello
world

or :

world
world
hello
hello

The first result explains : Enter the first round of the main coordination process for loop , The main coordinator gives up CPU Time slot , The above collaboration has not been created yet , So no other collaboration can use time slices , Then the main coordination process continues , First print hello. Enter the second round of the main coordination process for loop , The main coordinator gives up CPU Time slot , The above process is printed world, Then the main process gets the time slice and prints it hello, Before the main process ends , The above process is printed world.

The second result explains : Enter the first round of the main coordination process for loop , The main coordinator gives up CPU Time slot , The above collaboration has been created , And printed two world, Then the main coordination process continues , Printed a hello. Enter the second round of the main coordination process for loop , The main coordinator gives up CPU Time slot , There are no coordination processes waiting to be executed , So the main coroutine continues to print a hello, Then the end .


3、 ... and 、runtime.Goexit()

Exit the current collaboration , however defer The statement will execute as usual .

package main

import (
	"fmt"
	"runtime"
)

func main() {
    
	go func() {
    
		defer fmt.Println("A.defer")
		func() {
    
			defer fmt.Println("B.defer")
			runtime.Goexit() //  End the current collaboration 
			defer fmt.Println("C.defer")
			fmt.Println("B")
		}()
		fmt.Println("A")
	}()

	fmt.Println("main")
}

Output results :

main
B.defer
A.defer

or

main
B.defer

or

main

Before our own collaboration ends , Yes, the defined B.defer and A.defer Of , This explanation :

If we use runtime.Goexit() End of Association , Still execute defer sentence .

The first result explains : The main process prints main, A short period of time before the end of the main coordination process , Our cooperation has been carried out as soon as possible defer sentence : Print the B.defer and A.defer.

The second result explains : The main process prints main, A short period of time before the end of the main coordination process , Although our cooperation process is speeding up , But it only prints B.defer, No time to print A.defer.

The third result explains : The main process prints main, This time, although we are in a hurry, we are in a hurry , But it failed to catch up with the implementation defer sentence , It's all over .

To fully illustrate If we use runtime.Goexit() End of Association , Still execute defer sentence , We can delay the end of the main process :

package main

import (
	"fmt"
	"runtime"
	"time"
)

func main() {
    
	go func() {
    
		defer fmt.Println("A.defer")
		func() {
    
			defer fmt.Println("B.defer")
			runtime.Goexit() //  End the current collaboration 
			defer fmt.Println("C.defer")
			fmt.Println("B")
		}()
		fmt.Println("A")
	}()

	time.Sleep(time.Second) // Sleep for a while , Don't let the main coordination process end soon 
}

Output results :

B.defer
A.defer

Four 、runtime.GOMAXPROCS()

Golang By default, all tasks run in one cpu Nuclear interior , If you want to in goroutine Use multi-core in , have access to runtime.GOMAXPROCS Function modification , When the parameter is less than 1 Use the default value when .

Go The runtime scheduler uses GOMAXPROCS Parameter to specify how many OS Thread to execute at the same time Go Code . The default value is... On the machine CPU The core number . For example, in a 8 On the core machine , The scheduler will put Go The code is scheduled to 8 individual OS On the thread ( GOMAXPROCS yes m:n In scheduling n).

Go In language, you can use runtime.GOMAXPROCS() Function to set what the current program uses when it is concurrent CPU Logical core number .

Go1.5 Before the release , Single core execution is used by default .Go1.5 After the version , Default to use all of CPU Logical core number .

We can do this by assigning tasks to different CPU The core of logic is to realize the parallel effect , Here's an example :

package main

import (
	"fmt"
	"runtime"
	"time"
)

func a() {
    
	for i := 1; i < 10; i++ {
    
		fmt.Println("A:", i)
	}
}

func b() {
    
	for i := 1; i < 10; i++ {
    
		fmt.Println("B:", i)
	}
}

func main() {
    
	runtime.GOMAXPROCS(1)
	go a()
	go b()
	time.Sleep(time.Second)  // Sleep for a while , Don't let the main coordination process end 
}

In the above example , Two tasks have only one logical core , It's time to finish one task and then do another . Set the number of logical cores to 2, At this point, the two tasks are executed in parallel , The code is as follows :

package main

import (
	"fmt"
	"runtime"
	"time"
)

func a() {
    
	for i := 1; i < 10; i++ {
    
		fmt.Println("A:", i)
	}
}

func b() {
    
	for i := 1; i < 10; i++ {
    
		fmt.Println("B:", i)
	}
}

func main() {
    
	runtime.GOMAXPROCS(2)
	go a()
	go b()
	time.Sleep(time.Second)
}

Go The operating system thread in the language and goroutine The relationship between :

  1. One operating system thread has more than one user state goroutine.
  2. go Programs can use multiple operating system threads at the same time .
  3. goroutine and OS Threads are many to many relationships , namely m:n.

5、 ... and 、runtime.NumCPU()、runtime.GOROOT()、runtime.GOOS

package main

import (
	"fmt"
	"runtime"
)

func main() {
    
	// obtain cpu Nuclear quantity 
	fmt.Println("cpus:", runtime.NumCPU())
	// obtain goroot Catalog :
	fmt.Println("goroot:", runtime.GOROOT())
	// Get the operating system 
	fmt.Println("archive:", runtime.GOOS)
}

Output results :

cpus: 4
goroot: D:\Go
archive: windows

Reference link

  1. runtime package
  2. This paper introduces several runtime The most basic function in , To learn more about , Please refer to the article :go-runtime
原网站

版权声明
本文为[Cabbage that wants to become powerful]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202211605242764.html