繁体   English   中英

使用-race标志时,GO中的竞争条件意味着什么

[英]What is meant by race condition in GO when using -race flag

考虑以下代码:

package main

import (
    "fmt"
    "sync"
)

func main() {
var a int
m := new(sync.Mutex)

wg := sync.WaitGroup{}
wg.Add(2)

go func(){
    m.Lock()
    a = 2
    m.Unlock()
    wg.Done()
}()

go func(){
    //m.Lock()
    a = 9
    //m.Unlock()
    wg.Done()
}()

wg.Wait()

fmt.Println(a)
}

如果我们使用-race标志运行此代码,则会收到警告,提示存在竞争条件。

1)这种比赛状况可能会出什么问题?

如果我们取消注释第二个例程的锁,则不会收到竞争状况警告。 但是我们可以有不同的输出,因此存在竞争条件。

2)为什么现在我们没有种族状况警告?

1) 这种比赛状况可能会出什么问题?

  • 未定义的行为
  • 内存损坏
  • 从字面上看是崩溃的最糟糕的结果,即您不知道变量中可能有完全无效的值:p

2) 为什么现在我们没有种族状况警告?

互斥锁是可以保证原子性的原语。 取消注释锁后,运行时/操作系统将完全同步对锁保护的语句的访问。 a永远不会同时设置为2和9。

这可能会对性能产生影响(您的应用可能永远不会遇到它们),因为它们是序列化的操作。 通常这是一个很好的权衡,因为它可以确保正确性,但要以潜在的性能影响为代价。


go文档包含有关此问题的详细信息的惊人资源:

当必须以正确的顺序执行两个或多个操作时发生争用情况,但是由于编写程序的方式,它们没有这样做。

数据争用:一个并发操作尝试读取一个变量,而在另一个未确定的时间,另一个并发操作试图写入同一变量。

这个简单的示例有一个数据争用,因为我们正在读取a并进行打印,其中其他一些例程正在尝试更新该值。

package main

import "fmt"

func main() {
    var a int

    go func() {
        a++
    }()

    if a == 0 {
        fmt.Println("data:", a)
    }
}

输出可能性:

  1. a1并被打印( a0 ,在进入if块时,但在您打印时已更改。)
  2. a0 ,它被打印(更新尚未发生)
  3. 什么都不会打印,( a已更新)

来到您的问题:

1. 这种比赛状况可能会出什么问题?

答:

  1. 的输出a未定,或者也可以是29 。(如果您的第一go func()运行首先,将是9 ,如果第二func()运行第一, a将是2 )。
  2. 您在第二个func()更新a ,现在第一个func()运行并尝试更新,最后写入a函数将确定输出。它可以再次为29
  3. 假设在任何时候都只有一个goroutine持有锁,并且当它无法访问时,因为没有获得排他锁,因此没有其他变量写入该锁,但是如果任何共享变量不受锁保护,则可以使用锁访问变量并进行必要的更改。

2. 为什么现在我们没有种族状况警告?

答:

因为现在在任何时间运动只有一个够程可以访问a并进行更新。 但是即使现在a还是不确定的,最后运行哪个func()都会确定它。 (即使这是一种竞争条件,也可以通过适当的同步来克服这一情况)。

-race无法确定这种race条件,因为几乎不可能这样做。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM