[Basics of Go combat] Lightweight thread goroutine

Table of contents

1. Introduction

2. Data structure

1、G

2、P

3、M

Three, rookie combat

1. Create g008.go

2. Compile and run

3. Running results

1. Introduction

A goroutine is a lightweight thread in Go, also called a coroutine. In the Go language, each [concurrent] execution unit is called a goroutine, which is a lightweight thread. Each goroutine has a sched attribute to save its context, which can be switched in user mode without entering kernel mode, so the switching cost is very small.

As a concurrency tool of the Go language, goroutine is not only powerful but also easy to use, and the goroutine takes up very little memory, and independent concurrent tasks are relatively simple. You only need to use the go keyword to modify the function to enable a goroutine to run directly. Therefore, the development of go programs Many developers often use this concurrency tool.

2. [Data structure]

G, P, and M are the most important concepts for Go to achieve high concurrency. The runtime implements the mutual scheduling and execution of the three through the scheduler, and executes the dynamic binding between the user-mode g and the kernel-mode resource m through p. In order to reduce a series of performance problems caused by frequent creation of kernel-mode threads in the past, and give full play to the maximum and limited resources of the server.

1、G

G is short for goroutine, the smallest execution unit at runtime

struct  G 
{ 
    stackguard uintptr;       // The lower bound of the available space of the segment stack 
    stackbase uintptr;       // The stack base address of the segment stack 
    sched gobuf;         // When the process is switched, use sched to save the context 
    stack         stack ;         // The currently used stack space , including [lo, hi] two members 
    stackguard0 uintptr        // used to detect whether stack expansion is required, go code uses 
    stackguard1 uintptr        // used to detect whether stack expansion is required, native code uses 
    fnstart FuncVal*;      // run function 
    param         void *;         // pass parameter 
    status int16;         // status 
    goid int64;         // id number 
    mm*;           // m 
    lockedm muintptr       that g is currently bound to // does g require to go back to this M to execute 
    gopc uintptr;       // the pc that created this goroutine's go expression
    ...
};

2、P

P refers to Process, which is the resource required by M to run G, the basic scheduling unit of the coroutine scheduler, the shelter of G, and the bridge connecting G and M.

//  process structure 
type  p struct { 
   lock         mutex // mutex 
   id           int32 // id 
   status       uint32 // status of p, introduced later 
   link         puintptr // address of next p, please refer to g.schedlink 
   m            muintptr // m cache associated with p 
   mcache       *mcache // used when memory is allocated, and the mcache of m to which p belongs is also used

   goidcache     uint64 // The id obtained and cached from sched, to avoid allocating goidcacheend uint64 from sched every time goid 
   is  allocated

   runqhead  uint32 // p The queue formed by the goroutine of the local runnbale 
   runqtail  uint32 
   runq      [256]guintptr

   runnext  guintptr // the next executed g, if it is nil, get the next executed g from the queue

   gfree     *g // A list of g whose status is Gdead, which can be reused 
   gfreecnt  int32 
}

3、M

M refers to machine, which represents the operating system thread, which is the thread we often understand. It is the unit that really participates in the scheduling of the operating system. Each goroutine can only be executed if it is attached to a certain M.

// machine data structure 
type m struct { 
   g0 *g           // g0 is the special g used to schedule and execute system calls 
   curg *g           // m currently running g 
   p puintptr     // currently owned p 
   tls [ 6 ]uintptr   / / thread's local storage 
   nextp puintptr     // when m wakes up, m will have this p 
   id int64        // id 
   preemptoff     string       // if !="", continue to run curg 
   spinning       bool         // spin state, used to determine if m is working Has ended, and look for g to work 
   blocked        bool         // used to judge whether m is in sleep state 
   park note         // through this sleep and wake up m
   alllink *m           // A linked list composed of all m 
   schedlink muintptr     // The next m, through this field and sched.midle can be strung into a free linked list of m 
   mcache *mcache      // mcache, when m has p, it will put itself The mcache gives p 
   lockedg guintptr     // the corresponding value of 
   lockedm freelink *m           // the list of m to be released, strung into a linked list through sched.freem 
}

The relationship between the three GPMs is:

Three, rookie combat

Practical requirements: run a program with goroutines

Schedule now!

1. Create g008.go

/*
 * @Author: rookie combat
 * @FilePath: /go110/go-008/g008.go
 * @Description: goroutine
 */

package main

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

// test function 
func test_goroutine ( from  string ) {
     for i := 0 ; i < 3 ; i++ {
         // print the current sequence number 
        fmt.Println( from , ":" , i)
    }
}

func main() {
     // use the built-in function to print 
    println( "Hello" , "Rookie combat" )

    // start a goroutine 
    go test_goroutine ( "G" )

    // start a goroutine 
    go test_goroutine ( "M" )

    // start a goroutine 
    go func ( msg string ) {
        fmt.Println(msg)
    }("P")

    // wait
    time.Sleep(time.Second)

    fmt.Println("done")

    // current version 
    fmt.Printf( "Version: %s \n" , runtime.Version())
}

2. Compile and run

1. Generate module dependencies

go mod init g008

2. Compile

go build g008.go 

3. Compiled directory structure

└── go-008
    ├── g008
    ├── g008.go
    └── go.mod

4. Run

go run g008

3. Running results

Hello rookie combat
G : 0
G : 1
P
G : 2
M : 0
M : 1
M : 2
doneVersion
: go1.17.10 

Hello rookie combat
G : 0
G : 1
G : 2
P
M : 0
M : 1
M : 2
doneVersion
: go1.17.10 

Hello rookie combat
P
G : 0
G : 1
G : 2
M : 0
M : 1
M : 2
doneVersion
: go1.17.10 

Be a rookie, keep learning!

Leave a Comment

Your email address will not be published. Required fields are marked *