Implementation of golang concurrent programming

  • 2020-09-16 07:30:39
  • OfStack

go

The execution of the main function is itself a coroutine, and when the go keyword is used, a new coroutine is created

channel

The channel pipe is used to transmit signals between multiple coroutines

Cacheless pipe

When writing to an unbuffered channel, it blocks 1 until some coroutine reads the buffered channel

Blocking scenario:

There is no data in a channel, but a read channel is executed. There is no data in the channel. It writes data to the channel, but no coroutine reads it.

To sum up, the reads and writes of the non-cached channel must exist simultaneously and in two different coroutines


func main(){
  ch := make(chan int)
  
  go func(ch chan int){
    ch <-222
  }(ch)
  
  println(<-ch)
}

Buffered pipe

If there is cache, you can write data to the channel and return it directly. If there is cache, you can read data from the channel and return it directly. In this case, the cached channel will not block

Blocking scenario:

The channel caches no data, but executes a read channel. The channel cache is full and writes to the channel, but there is no coroutine read.

In summary, buffer channel reads and writes must be in two different coroutines


func main() {
  ch := make(chan int, 1) // Length of 1 Buffer pipes are also buffer pipes 
  ch <- 333
  go func(ch chan int) {
    println(<-ch)
  }(ch)
  ch <- 333
}

sync. Mutex and sync. RwMutex

sync. Mutex concurrent locks, only one concurrent lock can be loaded once

sync.RwMutex read-write lock, multiple read locks and one write lock can be loaded once. The read and write locks can no longer be loaded while the write lock exists

sync.WaitGroup

Blocking waits for all tasks to complete before continuing

WaitGroup is passed in a nonmethod. You need to pass a pointer


func main() {
  var wg sync.WaitGroup
  ch := make(chan int, 1000)
  for i := 0; i < 1000; i++ {
    wg.Add(1)
    go doSomething(i, &wg, ch)
  }
  wg.Wait()
  fmt.Println("all done")
  for i := 0; i < 1000; i++ {
    dd := <-ch
    fmt.Println("from ch:"+strconv.Itoa(dd))
  }
}

func doSomething(index int, wg *sync.WaitGroup, ch chan int) {
  defer wg.Done()
  fmt.Println("start done:" + strconv.Itoa(index))
  //time.Sleep(20 * time.Millisecond)
  ch <- index
}


Related articles: