Author: Lin Guanhong/The Ghost at my Fingertips

The Denver nuggets: juejin. Cn/user / 178526…

Blog: www.cnblogs.com/linguanh/

Making: github.com/af913337456…

Tencent cloud column: cloud.tencent.com/developer/u…


directory

  • preface
  • coroutines
  • Characteristics of coroutines
    • 12
    • Points 3 and 4 in characteristics
  • And threads as a whole

preface

Happy National Day everyone. It has been almost two months since my last post, and 19 years have come to an end. The current summary is more in the draft than issued, this time to share in detail in Go, thread and coroutine difference and relationship.

coroutines

Coroutine, English name Coroutine. But in Go, the English name for the coroutine is gorutine. It is often used for multitasking, or concurrent jobs. Yeah, the one for the multithreading homework.

Although we don’t have to write code like threads directly to do concurrency in Go, Go’s coroutines rely on threads to do so.

Let’s look at the differences.

The basic introduction of threads, here please do your own online search for articles, because there are many excellent introduction articles about threads.

Characteristics of coroutines

Here’s a straightforward list of thread characteristics, then parse them from the examples.

  1. Multiple coroutines can be managed by one or more threads,Scheduling of coroutinesOccurs in its thread.
  2. Can be scheduled. Scheduling policies are defined by application layer code and can be highly customized.
  3. High execution efficiency.
  4. Occupies less memory.

The above12

Let’s look at an example:

func TestGorutine(t *testing.T) {
	runtime.GOMAXPROCS(1)  // Specify a maximum P of 1, so that the maximum number of threads managed by coroutines is 1
	wg := sync.WaitGroup{} // Control exits the program until all coroutines are executed
	wg.Add(2)
	// Run a coroutine
	go func(a) {
		fmt.Println(1)
		fmt.Println(2)
		fmt.Println(3)
		wg.Done()
	}()

	// Run the second coroutine
	go func(a) {
		fmt.Println(65)
		fmt.Println(66)
		// Set a sleep so that the coroutine executes timeout and is suspended, causing timeout scheduling
		time.Sleep(time.Second)
		fmt.Println(67)
		wg.Done()
	}()
	wg.Wait()
}
Copy the code

The code snippet above runs two coroutines, and after running, the order of the output is observed to be staggered. May be:

65, 66, 1, 2, 3, 67Copy the code

It means that while executing coroutine A, it can interrupt at any time to execute coroutine line B, and coroutine B can also interrupt during execution to execute coroutine A.

It looks like coroutine A and B are running as thread switches, but notice that both A and B are running on the same thread. Their scheduling is not thread switching, but pure application state coroutine scheduling.

Why specify the following two lines of code in the above code?

runtime.GOMAXPROCS(1)
time.Sleep(time.Second)
Copy the code

This requires you to take a look at the basics of Go’s coroutine scheduling, as shown in my previous scheduling analysis article:

Go coroutine scheduling mechanism

If runtime.gomaxprocs (1) is not set, then the program will start a corresponding number of P’s based on the number of CPU cores in the operating system, resulting in multiple M’s, or threads. Then the coroutines in our program will be allocated to different threads. For demonstration purposes, set the number to 1, so that they are all allocated to the same thread, stored in the thread’s coroutine queue, waiting to be executed or scheduled.

Points 3 and 4 in coroutine characteristics.

  1. High execution efficiency.
  2. Occupies less memory.

Because the scheduling switch of coroutine is not thread switch, but controlled by the program itself, therefore, there is no overhead of thread switch, compared with multithreading, the more threads, the more obvious performance advantage of coroutine. Scheduling occurs in application state rather than kernel state.

The cost of memory, using the memory of the thread it is in, means that the memory of a thread can be used by multiple coroutines.

Secondly, the scheduling of coroutines does not need the locking mechanism of multithreading, because there is only one thread, and there is no simultaneous writing variable conflict, so the execution efficiency is much higher than multithreading.

And threads as a whole

Comparison of some thread coroutines
Data is stored Kernel state memory space Usually user-mode memory space provided by threads
Switching operation The operation is ultimately done at the kernel layer, where the application layer calls the syscall low-level functions provided by the kernel layer The application layer uses code for simple on-site save and restore
Task scheduling Implemented by the kernel, preemption mode, depends on various locks By the user – mode implementation of the specific scheduler. An example is the go coroutine scheduler
Voice support Most programming languages Some languages: Lua, Go, Python…
Implementation specification According to modern operating system specifications There is no uniform specification. Implemented by the developer at the application level, highly customizable, such as single-threaded threads. Different scheduling strategies, and so on

Personal ads

My technical book “Blockchain Ethereum DApp Development Combat” has been published and can be purchased online, suitable for elementary and intermediate blockchain technology related research and development personnel to read.