【有碼】go併發操作map的錯誤用例

kakashi發表於2017-04-28

map 在併發中是不安全的,需要用鎖。 錯誤的用鎖,依舊會報錯,如下程式碼是錯誤的用法,那麼問題來了,正確的應該是啥呢?

fatal error: concurrent map read and map write
package main

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

const MAX_TRFFIC uint64 = 10

type IpTriffic struct {
    Num    uint64
    Period int
}

type Trffic struct {
    sync.Mutex
    Period int
    List   map[string]uint64
}

func (m *Trffic) GetPeriod() int {
    period := math.Ceil(float64(time.Now().Unix() / 600))
    return int(period)
}

func (m *Trffic) ClearList() {
    m.Lock()
    m.List = make(map[string]uint64)
    m.Unlock()
}

func (m *Trffic) IncByKey(key string) {
    m.Lock()

    if _, ok := m.List[key]; !ok {
        m.List[key] = 1
    } else {
        m.List[key]++

        if m.List[key] > MAX_TRFFIC {
            fmt.Println("超過最大值", m.List[key])
        } else {
            fmt.Println(m.List[key])
        }
    }
    m.Unlock()
}

func (m *Trffic) Passport(key string) {

    period := m.GetPeriod()
    fmt.Println(period)

    /*if m.Period != period {
        m.ClearList()
    }
    */
    m.IncByKey(key)
}

var tc *Trffic

func init() {
    tc = &Trffic{}
    tc.Period = int(time.Now().Unix() / 600)
    tc.List = make(map[string]uint64)
}

func main() {

    for i := 0; i < 10000; i++ {
        go func() {
            tc.Passport("golang")
        }()
    }

    fmt.Println(tc.List, tc.Period)

}

更多原創文章乾貨分享,請關注公眾號
  • 【有碼】go併發操作map的錯誤用例
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章