The use of Golang Goroutine
- 2020-11-20 06:08:00
- OfStack
What is a Goroutine
goroutine is the core of Go's parallel design. goroutine is essentially a coroutine. It's smaller than threads. A dozen or so goroutine might be 56 threads at the bottom.
goroutine requires very little stack memory (about 4 to 5KB) to execute, and of course scales accordingly. Because of this, thousands of concurrent tasks can be run simultaneously. The goroutine is easier to use, more efficient and lighter than the thread.
Under normal circumstances, a typical computer running a few dozen threads would be a bit overloaded, but the same machine could easily have hundreds or thousands of goroutine competing for resources.
The creation of Goroutine
Just call the function ⽤ Add the go keyword before the statement to create concurrency ⾏ Unit.
Development & # 12040; The staff need not know any grasping ⾏ The scheduler will automatically assign it to the appropriate system thread for execution.
In concurrent programming, we usually want to split a procedure into several pieces and have each goroutine responsible for one block of work. When a program starts, the main function runs in a separate goroutine, which we call main goroutine. The new goroutine will be created using the go statement. The concurrent design of the go language makes it easy to achieve this goal.
Such as:
package main
import (
"fmt"
"time"
)
func foo() {
i := 0
for true {
i++
fmt.Println("new goroutine: i = ", i)
time.Sleep(time.Second)
}
}
func main() {
// create 1 a goroutine, The other 1 A task
go foo()
i := 0
for true {
i++
fmt.Println("main goroutine: i = ", i)
time.Sleep(time.Second)
}
}
Results:
[
main goroutine: i = 1
new goroutine: i = 1
new goroutine: i = 2
main goroutine: i = 2
main goroutine: i = 3
new goroutine: i = 3
...
Goroutine features
After the main go program exits, other sub-ES68en programs will exit automatically:
package main
import (
"fmt"
"time"
)
func foo() {
i := 0
for true {
i++
fmt.Println("new goroutine: i = ", i)
time.Sleep(time.Second)
}
}
func main() {
// create 1 a goroutine, The other 1 A task
go foo()
time.Sleep(time.Second * 3)
fmt.Println("main goroutine exit")
}
Operation results:
[
new goroutine: i = 1
new goroutine: i = 2
new goroutine: i = 3
main goroutine exit
runtime package
Gosched
runtime. Gosched() is used to transfer the CPU time slice occupied by the current go procedure, to give up the execution permission of the current goroutine, to arrange other waiting tasks to run, and to resume execution from the position of the transferred cpu the next time the cpu time slice is acquired.
A bit like a relay race, A runs 1 and touches the code ES104en.Gosched () and passes the baton to B. A rests, B runs on.
Such as:
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
// create 1 a goroutine
go func(s string) {
for i := 0; i < 2; i++ {
fmt.Println(s)
}
}("world")
for i := 0; i < 2; i++ {
runtime.Gosched()
fmt.Println("hello")
}
time.Sleep(time.Second * 3)
}
Operation results:
[
world
world
hello
hello
If runtime. Gosched() is not present, the result of the run is as follows:
[
hello
hello
world
world
Note: ES144en. Gosched() only gives one chance. Look at the code below and notice the result:
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
// create 1 a goroutine
go func(s string) {
for i := 0; i < 2; i++ {
fmt.Println(s)
time.Sleep(time.Second)
}
}("world")
for i := 0; i < 2; i++ {
runtime.Gosched()
fmt.Println("hello")
}
}
Operation results:
[
world
hello
hello
Why is world only once? Because as we said before, when master goroutine quits, other work goroutine quits automatically.
Goexit
Calling ES170en.Goexit () immediately terminates the current goroutine hold ⾏ , the scheduler ensures that all registered defer deferred calls are executed.
Note the difference with return, which returns the current function call to the caller.
Such as:
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
go func() {
defer fmt.Println("A.defer")
func() {
defer fmt.Println("B.defer")
runtime.Goexit() // Termination of the current goroutine
fmt.Println("B") // Do not perform
}()
fmt.Println("A") // Do not perform
}() // Don't forget ()
time.Sleep(time.Second * 3)
}
Operation results:
[
B.defer
A.defer
GOMAXPROCS
The call to runtime.GOMAXPROCS () is used to set the maximum number of CPU checks that can be computed in parallel, and returns the value set the previous time (if not the computer's default).
package main
import (
"fmt"
"runtime"
)
func main() {
runtime.GOMAXPROCS(1) // will cpu Set to a single core
for true {
go fmt.Print(0) // The child go cheng
fmt.Print(1) // The main go cheng
}
}
Operation results:
[
111111 ... 1000000 ... 0111 ...
When runtime.GOMAXPROCS (1) is executed, at most one goroutine is executed at a time. So it's going to print a lot of 1s. After a period of time, the GO scheduler will put it to sleep and wake up another goroutine, at which time it will start printing a lot of zeros. At the time of printing, goroutine is scheduled to the operating system thread.
package main
import (
"fmt"
"runtime"
)
func main() {
runtime.GOMAXPROCS(2)
for true {
go fmt.Print(0)
fmt.Print(1)
}
}
Operation results:
[
111111111111111000000000000000111111111111111110000000000000000011111111100000...
In the implementation
runtime.GOMAXPROCS(2)
, we used two CPU, so both goroutine can be executed 1 at a time, printing 0 and 1 alternately at the same frequency.
Other functions in the runtime package
Chinese document here: https: / / studygolang com/pkgdoc
Here is a simple list of functions and functions.
func GOROOT() string
GOROOT returns the root directory of Go. If an GOROOT environment variable exists, return the value of that variable. Otherwise, return the root directory where Go was created.
func Version() string
Returns the version string of Go. It is either hash submitted and the date it was created; Or release labels such as "go1.3".
func NumCPU() int
NumCPU returns the number of logical CPU Numbers (true · 8 cores) for the local machine.
package main
import (
"fmt"
"time"
)
func foo() {
i := 0
for true {
i++
fmt.Println("new goroutine: i = ", i)
time.Sleep(time.Second)
}
}
func main() {
// create 1 a goroutine, The other 1 A task
go foo()
time.Sleep(time.Second * 3)
fmt.Println("main goroutine exit")
}
0
GC performs a garbage collection once. (Call this function if you are desperate to do a garbage collection)