Go concurrency implements multiple solutions in the same step

  • 2020-06-15 09:14:46
  • OfStack

go's concise concurrency

Multi-core processors are becoming more and more popular. Is there an easy way to write software that unleashes the power of multiple cores? There is one. With the rise of programming languages designed for concurrency such as Golang, Erlang, Scala, and others, new concurrency patterns are becoming clear. As with procedural programming and object-oriented programming, a good programming model has an extremely compact kernel and extensive denotations on top of it. It can solve all kinds of problems in the real world. This paper takes GO language as an example to explain the kernel and denotation.

preface

Java has 1 series of thread synchronization methods, go has goroutine (coroutine), first look at the following code execution results?


 package main
 import (
   "fmt"
)
 func main() {
  go func() {
    fmt.Println("Goroutine 1")
  }()
  go func() {
    fmt.Println("Goroutine 2")
  }()
}

If you execute the above code, you probably won't see the output.

Because it is possible that the master coroutines end before the two are executed, and the master coroutines end by ending all other coroutines, the result of the code running is nothing.

It is estimated that many new contact go children's shoes will be depressed. How do you wait for the master coroutine created in the master coroutine to finish executing before ending the master coroutine?

Here are some solutions:

Sleep 1 period of time

The sleep 1 result may appear some time before the main method exits, as follows:


 package main
 import (
   "fmt"
  "time"
 )
 func main() {
   go func() {
    fmt.Println("Goroutine 1")
  }()
  go func() {
    fmt.Println("Goroutine 2")
  }()
  time.Sleep(time.Second * 1) //  sleep 1 Seconds, wait for the end of the two coroutines above 
}

The execution time of these two simple coroutines is very short, so you will find the results now.

[

Goroutine 1
Goroutine 2

]

Why did I say "may appear" above?

Since the time of sleep is currently set at 1s, if I perform a very complex logical operation in these two coroutines (the time is greater than 1s), I will find that it is still unprintable.

That's where the problem comes in: we can't be sure how much sleep we need

There is a problem with the above approach, but in go you can also use pipes for synchronization.

Pipeline synchronization

So how do you synchronize with pipes? show code:


 package main
 import (
   "fmt"
 )
 func main() {
   ch := make(chan struct{})
  count := 2 // count  Represents the number of coincidences of activities 
  go func() {
    fmt.Println("Goroutine 1")
    ch <- struct{}{} //  The coroutine ends and the signal is emitted 
  }()
  go func() {
    fmt.Println("Goroutine 2")
    ch <- struct{}{} //  The coroutine ends and the signal is emitted 
  }()
  for range ch {
    //  Each time from ch Received data in, indicating 1 The end of the coroutine for three activities 
    count--
    //  When all active coroutines have ended, close the pipe 
    if count == 0 {
      close(ch)
    }
  }
}

This approach is a perfect solution, goroutine/channel, which are often paired with one pair in go.

sync.WaitGroup

go also provides an easier way to do this -- use ES72en.WaitGroup.

WaitGroup, as the name implies, is used to wait for a set of operations to complete. Internally, WaitGroup implements a counter to record the number of outstanding operations. It provides three methods:

Add() is used to add counts Done() is used to call at the end of an operation to subtract 1 from the count Wait() is used to wait for all operations to complete, when the count becomes zero, and this function waits when the count is not zero and returns immediately when the count is zero

Continue show code:


package main
 import (
   "fmt"
  "sync"
 )
 func main() {
  var wg sync.WaitGroup
  wg.Add(2) //  Since there are two actions, increase 2 A count 
  go func() {
    fmt.Println("Goroutine 1")
    wg.Done() //  Operation complete, reduce 1 A count 
  }()
  go func() {
    fmt.Println("Goroutine 2")
    wg.Done() //  Operation complete, reduce 1 A count 
  }()
  wg.Wait() //  Wait until the count is zero 0
}

You will find that you can also see the results of the run, and it is easy to find this way.

conclusion


Related articles: