If ❤️ my article is helpful, welcome to like, follow. This is the biggest encouragement for me to continue my technical creation. More previous posts on my personal blog

Go concurrent programming

Golang supports goroutine concurrency with sync and Channel.

For example, let’s take an example of concurrent downloading of resources and implement two types of concurrent programming:

package main

import (
	"fmt"
	"sync"
	"time"
)

func main(a)  {
	// ============== sync ==============
	startTime1 := time.Now()

	testGoroutine()

	endTime1 := time.Now()
    // It can be seen that the serial download operation takes 3s, after the concurrent, only takes 1s
	fmt.Printf("======> Done! use time: %f",(endTime1.Sub(startTime1).Seconds()))
	fmt.Println()
}

// Using sync.waitgroup Multiple concurrent coroutines cannot communicate with each other until all concurrent coroutines have finished executing
var wg sync.WaitGroup
func testGoroutine(a) {
	for i:=0; i<3; i++ {
		wg.Add(1) // Wg.add () adds a count to WG; Wg.done () minus a count.
		go downloadV1("a.com/time_"+string(i+'0'))	// Start a new coroutine and execute the download function concurrently.
	}

	wg.Wait()	// wg.wait () : Wait for all coroutines to finish.
}


// ================= tool V =================
func downloadV1(url string) {
	fmt.Println("start to download", url)
	time.Sleep(time.Second) // The simulation takes time

	wg.Done()
}

Copy the code

Let’s take a closer look at two concurrency implementations

Sync.waitGroup

In the sync.waitGroup type, each WaitGroup internally maintains a count (starting at 0). If there is no need for communication between multiple concurrent coroutines, it is a good idea to use sync.waitgroup to wait for all concurrent coroutines to complete. The common methods for sync.waitgroup are as follows:

  • (wg * WaitGroup) Add(delta int) WaitGroup counter +1
  • (wg * WaitGroup) Done() WaitGroup counter -1
  • (WG * WaitGroup) Wait() blocks when the Wait group counter is not equal to 0 until it changes to 0.

Sync.waitgroup maintains a counter within the WaitGroup whose value can be increased or decreased by method calls. When we add N concurrent tasks to work, we increase the wait group’s counter value by N. At each task completion, this value is reduced by 1. At the same time, when the counter value of the waiting group in another Goroutine is 0, all tasks are completed. The steps are as follows:

  • Used when coroutines startwg.Add()Add +1 to the wait group count.
  • Used when coroutines startwg.Done()Count to wait group -1.
  • wg.Done()wg.Add(-1)Exactly equivalent. But if wg maintains the count insteadA negative number, will producePanic (panic).
  • Coroutine calledwg.Wait()When,
    • – wargaming is currently maintaining itCount to zero, then the wg.wait () operation isEmpty operation (NOOP);
    • Count forPositive integer, the coroutine will enterThe blocking stateWait for other coroutines to execute. This coroutine wg.wait () returns when another coroutine changes this count to 0.