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

我正在实现一个集成第三方 API 的应用程序,该 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")

    }

}


慕姐8265434
浏览 119回答 1
1回答

PIPIONE

任何对互斥体的访问都.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