加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

即使在golang中使用sync.Mutex也会出现竞争情况

发布时间:2020-12-16 09:27:31 所属栏目:大数据 来源:网络整理
导读:完整代码在这里: https://play.golang.org/p/ggUoxtcv5m go run -race main.go说那里有竞争条件我无法解释. 不过,该程序输出了正确的最终结果. 精华: type SafeCounter struct { c int sync.Mutex}func (c *SafeCounter) Add() { c.Lock() c.c++ c.Unlock(
完整代码在这里: https://play.golang.org/p/ggUoxtcv5m
go run -race main.go说那里有竞争条件我无法解释.
不过,该程序输出了正确的最终结果.

精华:

type SafeCounter struct {
    c int
    sync.Mutex
}

func (c *SafeCounter) Add() {
    c.Lock()
    c.c++
    c.Unlock()
}

var counter *SafeCounter = &SafeCounter{} // global

在增量器中使用* SafeCounter:

func incrementor(s string) {
    for i := 0; i < 20; i++ {
        x := counter
        x.Add()
        counter = x
    }
}

incrementor方法在main中生成两次:

func main() {
    go incrementor()
    go incrementor()
    // some other non-really-related stuff like
    // using waitGroup is ommited here for problem showcase
}

因此,正如我所说,去运行-race main.go将始终说有一个比赛cond发现.

此外,最终的结果总是正确的(至少我已经运行了多次这个程序,它总是说最终计数器是40,这是正确的).
但是,程序在开头打印不正确的值,所以你可以得到类似的东西:

Incrementor1: 0 Counter: 2
Incrementor2: 0 Counter: 3
Incrementor2: 1 Counter: 4
// ang the rest is ok

所以,那里缺少打印1.

有人可以解释为什么有竞争条件我的代码?

解决方法

你有很多种族条件,所有比赛都由比赛探测器指出:

x := counter      // this reads the counter value without a lock
    fmt.Println(&x.c)
    x.Add()
    counter = x       // this writes the counter value without a lock
    time.Sleep(time.Duration(rand.Intn(3)) * time.Millisecond)
    fmt.Println(s,i,"Counter:",x.c) // this reads the c field without a lock

> race#1在增量器中读取和写入计数器值之间> race#2是在incrementor中对计数器值的并发写入之间> race#3介于fmt.Println中x.c字段的读取和Add方法中x.c的增量之间.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读