dou7851 2016-12-06 09:28
浏览 41
已采纳

Go的种族探测器如何知道锁?

Adding lock to a program with race condition can solve the race condition and make the race detector quiet. How can Go's race detector be aware of lock?

Someone points out that "the race detector can only detect race conditions if and when they actually occur".

Consider the following program:

package main

import (
    "sync"
    "time"
)

func main() {
    var a int
    var wg sync.WaitGroup
    workers := 2
    wg.Add(workers)
    for i := 1; i <= workers; i++ {
        go func(sleep int) {
            time.Sleep(time.Duration(sleep) * time.Second)
            a = 1
            wg.Done()
        }(i * 5)
    }
    wg.Wait()
}

One goroutine sleeps for 5 seconds, another sleeps for 10 seconds, they don't write a at the same time in most cases, but the race detector prints the race condition warning every time. Why?

  • 写回答

2条回答 默认 最新

  • douye8500 2016-12-06 09:48
    关注

    The race detector does not analyze the source code, it doesn't know that you added locks in the source code.

    The race detector works at runtime:

    When the -race command-line flag is set, the compiler instruments all memory accesses with code that records when and how the memory was accessed, while the runtime library watches for unsynchronized accesses to shared variables.

    Because of this design, the race detector can only detect race conditions if and when they actually occur. So when you add proper locking / synchronization, the race condition will not happen (the if condition will not be met), and so no warning will be printed.

    See this blog post for more details: Introducing the Go Race Detector

    And this article: Data Race Detector

    Edit for your example:

    It may be that your 2 goroutines will never reach the point where they write the shared variable a at the same physical time (because the code runs so fast and the sleep time is relatively huge), but they run concurrently, in different goroutines, without explicit synchronization (a synchronization point may be channel communication, mutex lock/unlock etc.).

    The race condition does not imply that access to a shared variable does happen at the same time (one of which must be a write). The race condition is also met if access to a shared variable happens concurrently (from multiple goroutines), without synchronization. This can be detected at runtime by the race detector (due to the instrumented memory access code).

    Code generated by the compiler is allowed to use cached instances of the a variable in multiple goroutines, the runtime only has to guarantee that the cached instances are "refreshed" or disposed of if a synchronization point is reached. For details, see The Go Memory Model.

    Also note that time.Sleep() does not guarantee that execution will continue right after the specified duration, only that execution will be suspended for at least the specified duration (so the execution may continue at a later time):

    Sleep pauses the current goroutine for at least the duration d.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)
  • ¥15 Vue3地图和异步函数使用
  • ¥15 C++ yoloV5改写遇到的问题
  • ¥20 win11修改中文用户名路径
  • ¥15 win2012磁盘空间不足,c盘正常,d盘无法写入
  • ¥15 用土力学知识进行土坡稳定性分析与挡土墙设计
  • ¥70 PlayWright在Java上连接CDP关联本地Chrome启动失败,貌似是Windows端口转发问题
  • ¥15 帮我写一个c++工程
  • ¥30 Eclipse官网打不开,官网首页进不去,显示无法访问此页面,求解决方法
  • ¥15 关于smbclient 库的使用