[英]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) 这种比赛状况可能会出什么问题?
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)
}
}
输出可能性:
a
为1
并被打印( a
为0
,在进入if块时,但在您打印时已更改。) a
是0
,它被打印(更新尚未发生) a
已更新) 来到您的问题:
1. 这种比赛状况可能会出什么问题?
答:
a
未定,或者也可以是2
或9
。(如果您的第一go func()
运行首先,将是9
,如果第二func()
运行第一, a
将是2
)。 func()
更新a
,现在第一个func()
运行并尝试更新,最后写入a
函数将确定输出。它可以再次为2
或9
。 2. 为什么现在我们没有种族状况警告?
答:
因为现在在任何时间运动只有一个够程可以访问a
并进行更新。 但是即使现在a
还是不确定的,最后运行哪个func()
都会确定它。 (即使这是一种竞争条件,也可以通过适当的同步来克服这一情况)。
-race
无法确定这种race
条件,因为几乎不可能这样做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.