go concurrent programming WaitGroup, Mutex

1. Background

Record it, to facilitate writing code directly after use.
Note that:

  • chan default support multi-coroutines work, no lock.
  • Other variable operation requires the use of a lock protection (map multiprotocol concurrent write process will panic, and can not be captured).
  • When you start goroutine, usually you need to pass parameters. Local variables are not read.
  • Waitgroup need to wait for the exit of all goroutine (even if some need to panic goroutine appear wg.Done ())
  • Each goroutine must capture panic, panic would otherwise cause the process will hang.

2. Unified panic judgment function: COMMON_PANIC_CAPTURE

Encountered at work, due to the panic log print is not uniform or omission has appeared in panic monitoring.
Analyzing by encapsulating panic function, unified log printing, added to facilitate the monitoring, avoiding false negative situation.

package main

import (
    "fmt"
    "runtime/debug"
    "sync"
    "time"
)

func COMMON_PANIC_CAPTURE(panicErr interface{}) (bool){ //封装一个panic判断/日志打印函数
    if panicErr != nil {
        fmt.Printf("PANIC err:%v, stack:%s\n", panicErr, debug.Stack())
        return true
    }
    return false
}

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 3; i=i+1 {
        go func(x int){  //启动go时, 需要注意参数传递
            wg.Add(1)
            defer func() {
                wg.Done()
                COMMON_PANIC_CAPTURE(recover())
            }()
            if x == 2 {
                panic(fmt.Sprintf("val:%d", x))
            }
        }(i)
    }
    wg.Wait()   //等待go结束
    time.Sleep(2 * time.Second) //等待go panic日志打印
    fmt.Printf("end ok!\n")
}

3. Concurrent programming examples

Concurrent write map panic, the program can not be captured, can be a problem go design.

package main

import (
    "fmt"
    "sync"
    "encoding/json"
)

func main() {
    res := make(map[string]string)
    var wg sync.WaitGroup   //group, 内部使用atomic实现计数
    var mylock sync.Mutex

    for i := 0; i < 4000; i++ {
        wg.Add(1)
        go func(par int){
            defer func() {
                wg.Done()
            }()

            //time.Sleep(3 * time.Second)
            tmp := fmt.Sprintf("%d", par %7)

            mylock.Lock()  //加锁
            defer mylock.Unlock()  //defer确保解锁
            res[tmp] = tmp
        }(i)
    }
    wg.Wait()

    resByte, _ := json.Marshal(res)
    fmt.Printf("%s\n", string(resByte))
}

Guess you like

Origin www.cnblogs.com/xudong-bupt/p/10959110.html