Develop blockchain applications from scratch (10)--the use of golang coroutines

1. What is concurrency

1.1 Concurrency Definition

In order to explain this concept more interestingly, I borrowed an answer on Zhihu: You are halfway through your meal, and the call comes, and you don’t pick it up until after you finish eating, which means that you do not support concurrency or parallelism. When you are halfway through your meal, the phone calls, you stop to answer the phone, and then continue to eat, which means that you support concurrency. When you are halfway through your meal, the phone comes, and you eat while on the phone, which shows that you support parallelism. The key to concurrency is your ability to handle multiple tasks, not necessarily at the same time. The key to parallelism is your ability to handle multiple tasks at the same time. Corresponding to the CPU, if it is multi-core, it has the ability to execute at the same time, that is, it has the ability to parallelize. For the Go language, it arranges our code for concurrency and parallelism by itself.

1.2 The benefits of concurrency

2. What is a coroutine

2.1 Coroutine Definition

A coroutine is a user-mode lightweight thread, also known as a micro-thread.

In a go program, the go language automatically creates and destroys system-level threads at runtime. System-level threads refer to threads provided by the operating system.

Then the corresponding user-level threads refer to those built on system-level threads. The creation, destruction, scheduling, and state changes of user-level threads all need to be implemented and processed by our programs.

Compared with threads, the cost of creating a gotoutine is very small, it is just a piece of code, a function entry

2.2 Advantages of coroutines

The creation and destruction of coroutines do not need to be done by the operating system. Therefore, there is no thread switching overhead, so the speed will be very fast, which can improve task concurrency

Three, golang coroutine practice

A coroutine is similar to a thread, but is scheduled by Go instead of the operating system. Code running in a coroutine can run concurrently with other code. Let's look at one

package main

import (
  "fmt"
  "time"
)

func main() {
  fmt.Println("start")
  go process()
  time.Sleep(time.Millisecond * 10) // this is bad, don't do this!
  fmt.Println("done")
}

func process() {
  fmt.Println("processing")
}

There are some interesting things here, but the most important is how we start a coroutine. We just use the go keyword and then use the function we want to execute. If we only want to run part of the code, as mentioned above, we can use anonymous functions. It should be noted that anonymous functions can be used not only in coroutines, but also in other places.

go func() {
  fmt.Println("processing")
}()

Coroutines are easy to create and have little overhead. Eventually multiple coroutines will run on the same underlying operating system thread. This is also commonly referred to as the M:N threading model because we have M application threads (coroutines) running on N operating system threads. As a result, the overhead of a coroutine is relatively low (several kilobytes) compared to system threads. On modern hardware, it is possible to have millions of coroutines.

Also, the complexity of mapping and scheduling is hidden here. We just need to say that this code needs to execute concurrently and let Go implement it itself.

If we go back to our example, you'll notice that we use Sleep to make the program wait a few milliseconds. This is because the coroutine will have a chance to execute before the main process exits (the main process will not wait for all coroutines to complete execution before exiting). To fix this, we need to coordinate our code.

Guess you like

Origin blog.csdn.net/cljdsc/article/details/122675314
Recommended