为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
HUWWW 2022-04-26 16:06:16
我正在实现一个应用程序,该应用程序集成了每秒点击次数限制的第三方 API。我编写了我的适配器并且我是一个快乐的人,直到我使用竞争条件检测器运行我的测试。设计很简单,有一个:计算它发出的请求的结构每秒将此计数器重置为 0 的滴答声此结构上的私有函数在满足条件之前一直阻塞,以允许对 API 进行额外调用。运行这个测试用例效果很好,直到你给它-race标志。我相信数据竞争是由试图重置命中计数器的滴答线程和增加它的调用请求引起的......我的设计是坏的还是我应该忍受数据竞争警报?import (    "sync"    "testing"    "time")var subject httpClientWrapperfunc 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.Mutexfunc (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")    }}
查看完整描述

1 回答

?
catspeake

TA贡献1111条经验 获得超0个赞

任何访问都.hits应该在互斥体后面,所以


// reset hits every second to 0

go func() {

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

    for range tick {

        m.Lock()

        subject.hits = 0

        m.Unlock()

    }

}()

此外,任何睡眠都不应该在互斥锁锁定的情况下发生,所以


m.Lock()

...

    {

        m.Unlock()

        // cool down for one second

        time.Sleep(1 * time.Second)

        m.Lock()

        ...

    }

...

m.Unlock()


查看完整回答
反对 回复 2022-04-26
  • 1 回答
  • 0 关注
  • 170 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号