亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

減少并發 Set 帶來數據競爭

減少并發 Set 帶來數據競爭

Go
拉莫斯之舞 2023-07-26 15:41:11
我正在針對我的 redigo 函數運行此測試,看看它是否支持大量并發寫入,這是代碼import (    "github.com/gomodule/redigo/redis"    "log"    "os")// Redis connection poolvar RedisPool *redis.Poolfunc InitPool() {    RedisPool = &redis.Pool{        MaxIdle:   80,        MaxActive: 12000,        Dial: func() (redis.Conn, error) {            conn, err := redis.Dial("tcp", "127.0.0.1:6379")            if err != nil {                log.Printf("ERROR: fail init redis: %s", err.Error())                os.Exit(1)            }            return conn, err        },    }}func ClosePool() error {    return RedisPool.Close()}func Set(key string, val string) error {    // get conn and put back when exit from method    conn := RedisPool.Get()    defer conn.Close()    _, err := conn.Do("SET", key, val)    if err != nil {        log.Printf("ERROR: fail set key %s, val %s, error %s", key, val, err.Error())        return err    }    return nil}func TestManySets(t *testing.T) {    InitPool()    defer ClosePool()    var wg sync.WaitGroup    numOfOperations := 1000    for i := 0; i < numOfOperations; i++ {        wg.Add(1)        go func() {            err := Set("key", strconv.Itoa(i))            if err != nil {                t.Errorf("error when setting key value: %s", err)            }            wg.Done()        }()    }    wg.Wait()    result, err := Get("key")    if err != nil {        t.Errorf("error when getting key value: %s", err)    }    t.Logf("result: %s", result)}當運行測試時,go test -run TestManySets /path/to/package -count 1 -v我遇到了很多EOF錯誤;當使用 運行測試時-race,即go test -race -run TestManySets /path/to/package -count 1 -v我檢測到大量數據競爭,任何人都可以向我指出如何才能使事情正確?
查看完整描述

1 回答

?
一只名叫tom的貓

TA貢獻1906條經驗 獲得超3個贊

競爭是因為你的 for 循環正在更新,i而你的 goroutine 正在i同時讀取。解決這個問題的一種方法是傳遞i給你的 goroutine 函數:


for i := 0; i < numOfOperations; i++ {

? ? wg.Add(1)

? ? go func(i int) {? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// <----------- CHANGE THIS

? ? ? ? err := Set("key", strconv.Itoa(i))

? ? ? ? if err != nil {

? ? ? ? ? ? t.Errorf("error when setting key value: %s", err)

? ? ? ? }

? ? ? ? wg.Done()

? ? }(i)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// <----------- AND THIS

}

這樣你就不再有一個閉包i,并且i你的 goroutine 函數內部是一個獨特的值,可以在不受外部干擾的情況下讀?。ɑ驅懭耄?。


這還解決了競爭檢測器找不到的另一個錯誤:在循環中for,重復使用遞增的變量,這意味著您當前的版本實際上i在許多情況下無意中使用相同的值,并跳過其他值。


查看完整回答
反對 回復 2023-07-26
  • 1 回答
  • 0 關注
  • 118 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號