想要数据竞赛还是糟糕的设计?

我正在实现一个应用程序,该应用程序集成了每秒点击次数限制的第三方 API。我编写了我的适配器并且我是一个快乐的人,直到我使用竞争条件检测器运行我的测试。

设计很简单,有一个:

  • 计算它发出的请求的结构

  • 每秒将此计数器重置为 0 的滴答声

  • 此结构上的私有函数在满足条件之前一直阻塞,以允许对 API 进行额外调用。

运行这个测试用例效果很好,直到你给它-race标志。我相信数据竞争是由试图重置命中计数器的滴答线程和增加它的调用请求引起的......

我的设计是坏的还是我应该忍受数据竞争警报?


import (

    "sync"

    "testing"

    "time"

)


var subject httpClientWrapper


func init() {

    subject = httpClientWrapper{

        hits:       0,

        hitsSecond: 1,

    }

    // reset hits every second to 0

    go func() {

        tick := time.Tick(1 * time.Second)

        for range tick {

            subject.hits = 0

        }

    }()

}


type httpClientWrapper struct {

    hits, hitsSecond int

}


var m sync.Mutex


func (c *httpClientWrapper) allowCall() {

    m.Lock()

    callAllowanceReached := c.hits >= c.hitsSecond

    for callAllowanceReached {

        // cool down for one second

        time.Sleep(1 * time.Second)

        callAllowanceReached = c.hits >= c.hitsSecond

    }

    c.hits = c.hits + 1

    m.Unlock()

}


func TestItSleeps(t *testing.T) {

    timeStart := time.Now()

    var wg = sync.WaitGroup{}

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

        wg.Add(1)

        go func() {

            subject.allowCall()

            wg.Done()

        }()

    }

    wg.Wait()

    elapsedTime := time.Since(timeStart)

    if elapsedTime < (1 * time.Second) {

        t.Errorf("this test should not had been able to run in less than a second due to locks and cool down")

    }

}


HUWWW
浏览 171回答 1
1回答

catspeake

任何访问都.hits应该在互斥体后面,所以// reset hits every second to 0go func() {&nbsp; &nbsp; tick := time.Tick(1 * time.Second)&nbsp; &nbsp; for range tick {&nbsp; &nbsp; &nbsp; &nbsp; m.Lock()&nbsp; &nbsp; &nbsp; &nbsp; subject.hits = 0&nbsp; &nbsp; &nbsp; &nbsp; m.Unlock()&nbsp; &nbsp; }}()此外,任何睡眠都不应该在互斥锁锁定的情况下发生,所以m.Lock()...&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; m.Unlock()&nbsp; &nbsp; &nbsp; &nbsp; // cool down for one second&nbsp; &nbsp; &nbsp; &nbsp; time.Sleep(1 * time.Second)&nbsp; &nbsp; &nbsp; &nbsp; m.Lock()&nbsp; &nbsp; &nbsp; &nbsp; ...&nbsp; &nbsp; }...m.Unlock()
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go