This is the 21st article in the “Learn to Go” series

Concurrency and parallelism

When it comes to concurrency, I’m sure you’ve heard of parallelism. Let me show you the difference between the two, and then talk about concurrency in Go.

Parallelism is a very simple concept, which means simultaneous execution, the ability to perform multiple tasks at one point in time. The easiest way to achieve parallelism is through multi-threading, or multi-processing, so that more than one task can be performed at the same time. A single thread can never achieve a parallel state. Concurrency is the ability to process more than one task at a time. We often say that a program is designed concurrently, that is, it allows multiple tasks to be executed simultaneously, which means over a period of time. Concurrency is implemented by executing multiple tasks at intervals in a single thread. It can be said that multi-threading or multi-process is the foundation of parallelism, but single threading also achieves concurrency through coroutines.

A common example is a single-core computer that can download and listen to music. In fact, both tasks are performed this way, but the switching time between the two tasks is short and gives the impression that they are being performed simultaneously.

Go through coroutines to achieve concurrency, coroutines by channel communication, this article first to introduce the use of coroutines, and then write a way.

coroutines

Goroutines can be thought of as lightweight threads, but they have very little overhead compared to threads. As a result, Go applications can typically run thousands of coroutines concurrently. Go Creating a coroutine is as simple as preending a method or function call with the keyword Go.

func printHello(a) {
	fmt.Println("hello world goroutine")}func main(a) {
	go printHello()    // Create a coroutine
	fmt.Println("main goroutine")}Copy the code

Output:

main goroutine
Copy the code

The code above, line 6, creates the coroutine with the go keyword, and now has two coroutines, the newly created coroutine and the main coroutine. The printHello() function will execute concurrently, independent of the main coroutine. Yes, you read that right, the output of the program is like this, don’t you believe me? You can actually run the program. You’re wondering, why printHello() doesn’t output, what’s going on? When the coroutine is created, the main function immediately returns to execute the next line of code, unlike a function call, which waits for the function to complete. The main coroutine is done, the program exits, the printHello coroutine exits, and there is no output.

Modify the code:

func printHello(a) {
	fmt.Println("hello world goroutine")}func main(a) {
	go printHello()
	time.Sleep(1*time.Second)
	fmt.Println("main goroutine")}Copy the code

After the coroutine is created, the main coroutine sleeps for 1s to allow the printHello coroutine to execute.

hello world goroutine
main goroutine
Copy the code

Create multiple coroutines

As mentioned in the last section, you can create multiple coroutines. Here’s an example:

func printNum(a) {
	for i := 1; i <= 5; i++ {
		time.Sleep(20 * time.Millisecond)
		fmt.Printf("%d ", i)
	}
}
func printChacter(a) {
	for i := 'a'; i <= 'e'; i++ {
		time.Sleep(40 * time.Millisecond)
		fmt.Printf("%c ", i)
	}
}
func main(a) {
	go printNum()
	go printChacter()
	time.Sleep(3*time.Second)
	fmt.Println("main terminated")}Copy the code

In addition to the main coroutine, the above code creates two new coroutines: printNum and printChacter. PrintNum coroutine prints five numbers every 20 milliseconds, printChacter coroutine prints letters every 40 milliseconds. After creating these two coroutines, the main coroutine sleeps for 1s and waits for other coroutines to complete. Program output (your output may be different from mine) :

1 a 2 3 b 4 5 c d e main terminated
Copy the code

Then again, waiting for the coroutine to complete by adding time.sleep () is a “dark art.” In a real production environment, we cannot add random sleep calls to the main coroutine and wait for other coroutines to complete, regardless of whether we know how long it will take for other coroutines to complete. So what? Go provides us with a channel, which can notify the main coroutine when the coroutine is executed, and also realize the communication between coroutines. We’ll talk about that next time.

Anonymous coroutines

As I mentioned in the functions article, there are anonymous functions, and calling an anonymous function with the keyword go is an anonymous coroutine. Let’s modify the previous example:

func main(a) {
	go func(a) {
		fmt.Println("hello world goroutine")
	}()
	time.Sleep(1*time.Second)
	fmt.Println("main goroutine")}Copy the code

The output is the same as before.

Hope this article brings you a harvest, Good Day!


Original article, if need to be reproduced, please indicate the source! Check out “Golang is coming” or go to seekload.net for more great articles.

Prepare for you to learn Go language related books, public number background reply [ebook] receive!