为什么不读/写其内容的结构体的方法仍然会导致竞争情况?

2024-01-24

From 戴夫·切尼博客 http://dave.cheney.net/2015/11/18/wednesday-pop-quiz-spot-the-race,以下代码显然会导致竞争情况,只需更改即可解决func (RPC) version() int to func (*RPC) version() int :

package main

import (
        "fmt"
        "time"
)

type RPC struct {
        result int
        done   chan struct{}
}

func (rpc *RPC) compute() {
        time.Sleep(time.Second) // strenuous computation intensifies
        rpc.result = 42
        close(rpc.done)
}

func (RPC) version() int {
        return 1 // never going to need to change this
}

func main() {
        rpc := &RPC{done: make(chan struct{})}

        go rpc.compute()         // kick off computation in the background
        version := rpc.version() // grab some other information while we're waiting
        <-rpc.done               // wait for computation to finish
        result := rpc.result

        fmt.Printf("RPC computation complete, result: %d, version: %d\n", result, version)
}

查看代码几次后,我很难相信代码存在竞争情况。然而,当使用 --race 运行时,它声称有一个写入rpc.result=42以及之前的阅读version := rpc.version()。我理解写入,因为 goroutine 改变了值rpc.result,但是读取呢?在哪里version()方法是否发生读取?它不会触及 rpc 的任何值,只是返回 1。

我想了解以下内容:

1) 为什么该特定行被视为对 rpc 结构的读取?

2)为什么要改变RPC to *RPC解决种族案件?


当你有一个带有像这样的值接收器的方法时:

func (RPC) version() int {
    return 1 // never going to need to change this
}

你调用这个方法:

version := rpc.version() // grab some other information while we're waiting

必须从该值制作副本rpc,它将传递给方法(用作接收者值)。

所以当一个 goroutinego rpc.compute()正在运行并正在修改rpc结构体值(rpc.result = 42),主 goroutine 正在复制整个rpc结构值。那里!这是一场比赛。

当你修改接收者类型为指针时:

func (*RPC) version() int {
    return 1 // never going to need to change this
}

你调用这个方法:

version := rpc.version() // grab some other information while we're waiting

这是一个简写

version := (&rpc).version()

这传递了地址rpc价值RPC.version(),它仅使用指针作为接收者,因此不会复制rpc结构值。由于结构中没有任何内容被使用/读入RPC.version(),没有种族。

Note:

请注意,如果RPC.version()会读到RPC.result字段,这也将是一场竞赛,因为一个 Goroutine 会修改它,而主 Goroutine 会读取它:

func (rpc *RPC) version() int {
    return rpc.result // RACE!
}

Note #2:

另请注意,如果RPC.version()会阅读另一个领域RPC没有被修改RPC.compute(),这不会是一场比赛,例如:

type RPC struct {
    result int
    done   chan struct{}
    dummy  int
}

func (rpc *RPC) version() int {
    return rpc.dummy // Not a race
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么不读/写其内容的结构体的方法仍然会导致竞争情况? 的相关文章

  • C 中的可重入和可重入?

    我正在读一本书 名叫Linux系统编程 引用这本书里的话 系统调用和其他库函数怎么样 如果你的 进程正在写入文件或分配内存 并且信号处理程序写入同一文件或还调用 malloc 有些函数显然是不可重入的 如果一个程序在 执行不可重入函数的中间
  • vscode 中的调试不会在断点处停止,调试器启动时显示“无法找到文件...”

    乌班图 vscode 1 62 1 去1 17 3 vscode go 扩展 v0 29 0 深入研究 v1 7 1 我是 vscode 和 Go 的新手 我有多年在 Eclipse 中调试 Java 应用程序的经验 我构建了一个小型多模块
  • 当变量更新时动态刷新模板的一部分golang

    在Golang中 当变量更新时可以刷新模板的一部分吗 例如 我们可以在 Angular js 中找到这一点 基本上在我的代码中 我通过 ajax 中的邮政编码查找地址 它显示我找到的该邮政编码的用户列表 Here is a sample o
  • 易失性结构=结构不可能,为什么?

    struct FOO int a int b int c volatile struct FOO foo int main void foo a 10 foo b 10 foo c 10 struct FOO test foo return
  • Go API 在 html 中显示 swagger api 规范 (json) (Swagger UI)

    我有一个服务于特定端口的应用程序 gorilla mux 我也有一个 json 文件形式的 swagger API 规范 是否有任何 go API 可以像 spring boot 一样从 JSON 文件生成 swagger UI 定义 我正
  • OpenMP while 循环中的手动同步

    我最近开始使用 OpenMP 为大学的一个项目做一些 研究 我有一个矩形且均匀分布的网格 在该网格上我使用迭代方案求解偏微分方程 因此 我基本上有两个 for 循环 网格的 x 方向和 y 方向各一个 并由 while 循环包裹以进行迭代
  • 我应该在请求中创建 executorService 还是在 Web 应用程序中共享一个实例?

    我正在向基于 Jersey 的 Web 服务添加一个新端点 支持端点的逻辑需要对另一个服务进行 10 到 50 次调用 这些调用是独立的并且可以并行化 因此我正在考虑使用执行器服务将工作分配到多个线程 我想知道是否应该为每个请求实例化一个
  • 如何在 Go 中表示可选字符串?

    我希望建模一个可以有两种可能形式的值 不存在或字符串 执行此操作的自然方法是Maybe String or Optional
  • 代表和结构的速度问题

    我遇到了一些与结构和委托有关的速度问题 采用以下控制台应用程序代码 public delegate string StringGetter public class LocalString public LocalString string
  • 无法通过键获取 Gorilla 会话值

    我无法通过这种方式从会话中获取价值 它是nil session initSession r valWithOutType session Values key 完整代码 package main import fmt github com
  • 按引用或按值扫描功能

    我有以下代码 statement SELECT id from source where mgmt 1 var exists string errUnique dr db QueryRow statement mgmt Scan exist
  • C 中的空结构

    我有一个没有成员的结构 目前 我想知道是否可以抑制我收到的警告 warning struct has no members 是否可以添加会员并保留sizeof结构零 还有其他解决方案吗 在 c 中 空结构的行为取决于编译器 而在 c 中 空
  • 使用 testify 模拟接口方法两次,输入和输出不同

    如何在 golang 测试中模拟接口方法两次 例如 type myCache interface Get key string data interface error type service struct cache myCache f
  • 释放c循环中的子字符串

    我正在尝试为结构体的每个成员获取一个子字符串 structs 然后将该子字符串分配给temp struct 我遇到的问题是如何在每次迭代时释放子字符串 但是由于某种原因代码运行valgrind抛出一个Invalid read of size
  • Gorm 总是返回带有 nil 值的结构

    我正在使用 Gorm 构建 Go Web API 作为 Amazon RDS 中 Postgresql 数据库的 ORM 问题是 Gorm 总是返回一片结构 其值全部为零 尽管数据库已经填充了数据 切片中的结构体数量是否合适取决于LIMIT
  • Golang中如何获得100%的代码覆盖率? [复制]

    这个问题在这里已经有答案了 我无法获得 100 的代码覆盖率 因为我无法在 Golang 中测试 Fatals 我发现了一些问答 包括this one https stackoverflow com questions 30688554 h
  • C 位域内存使用情况

    我需要处理以下形式的一些数据 typedef struct unsigned n1 12 unsigned n2 12 unsigned n3 12 unsigned n4 1 unsigned n5 35 data 我确保它们总共最多有
  • 为什么 i++ 不是原子的?

    Why is i Java 中不是原子的 为了更深入地了解 Java 我尝试计算线程中循环的执行频率 所以我用了一个 private static int total 0 在主课中 我有两个线程 主题 1 打印System out prin
  • 结构对类型大小的贡献

    我想知道为什么有以下两种类型 struct double re 2 and double re 2 C 中的大小相同吗 struct 不会增加一点大小开销吗 不 它只是将所有元素组合成一个更高级别的元素 其大小只是各个元素大小的总和 加上一
  • 查找c中结构元素的偏移量

    struct a struct b int i float j x struct c int k float l y z 谁能解释一下如何找到偏移量int k这样我们就可以找到地址int i Use offsetof 找到从开始处的偏移量z

随机推荐

  • PHP file_get_contents 在本地主机上不起作用

    我正在从 localhost http 172 16 65 1 上的 OSX 上的 MAMP 服务器上处理我的网站 我想从 Google 加载一些 JSON 一些简单的测试表明我在这里遇到了问题 echo file get contents
  • 使用 JAVA 8 Streams 从地图中仅创建 1 个列表,其中地图值是列表

    我有一个地图 其中 值 是项目列表 Map
  • 如何在MVVMCross WPF应用程序中实现关闭按钮?

    我在用MVVM交叉 in my WPF申请 我想提供一个Close or ExitGUI 中的 按钮可关闭整个应用程序 有没有一种简单的方法可以使用MVVM交叉功能 我用我的方法尝试了以下方法MainViewModel public cla
  • 在 Rust 中散列读者的正确方法?

    我试图使用双重哈希 https crates io crates twox hash为文件生成哈希 因为它似乎是最快的哈希实现 并且安全性不是此实现的问题 为了让它与读者一起工作 我实现了一个包装结构 它实现了Write特质并直接调用XxH
  • 在类中存在的标头内使用“导航”和“路线” - React-navigation v5

    我被困住了 因为我想切换到 React navigation 的 V5 版本 在 v4 中 我曾经传递参数并将它们与以下命令一起使用 Set this props navigation navigate MyDestination myPa
  • 在引导程序中禁用@media print?

    是否可以完全禁用任何预配置 media printcss样式来自bootstrap无需重新编译 默认应用的打印样式可以在这里看到 https github com twbs bootstrap blob master dist css bo
  • 工具提示控件如何通过新属性增强表单上的所有控件?

    在回答另一个问题时 我开始想知道如何向表单中的所有控件添加新属性 就像工具提示控件那样 例如 我可以使用它将 IsDirty 标志添加到所有文本框 只需将组件添加到表单中 它就会为每个文本框处理这个问题 将工具提示控件添加到表单时 所有控件
  • 浏览器关闭时如何唤醒服务人员

    我正在玩服务人员的东西 我已经做了它以及清单 json 我想在以下场景后触发服务工作人员启动 添加了推送集成并从服务器端发送推送通知 在客户端收到它 但前提是我在我的申请页面中 以下是我想要尝试启动 Service Worker 的步骤 我
  • 如何使用 qmake 处理两个同名的源文件?

    我的 Qt 项目有两个同名但位于不同文件夹中的源文件 专业文件是 SOURCES A Test cpp SOURCES B Test cpp 它可以通过 Qt Visual Studio 插件生成 Visual Studio 解决方案文件
  • github api 比较提交,响应状态存在分歧

    在配置jenkins时 我想检测feature分支是否存在合并冲突 所以我使用github api v3在2上进行测试故意的冲突的分支 将branch1合并到master后 我比较了branch2 b2 如下所示 curl i https
  • WS-Security php 中 PasswordDigest 的工作算法

    我一直根据航空公司供应商提供的公式创建哈希密码 我在这个网站上搜索过 我从下面的链接中得到了 C 的解决方案 但我想要 PHP 的解决方案 WS Security 中 PasswordDigest 的工作算法 https stackover
  • 了解 Objective-C 中强指针和弱指针的实际应用

    我刚刚阅读了已接受的优秀答案this https stackoverflow com questions 9262535 explanation of strong and weak storage in ios5这个问题澄清了 Objec
  • JavaScript 输入数字

    如何使用 window prompt 从用户处获取 2 个数字并将它们相加而不连接 我的想法是 var temp window prompt Number1 var temp2 window prompt Number2 var answe
  • 初始化列表和运算符的 RHS

    我不明白为什么初始化列表不能在运算符的 RHS 上使用 考虑 class foo struct bar template
  • javafx拉伸图像以填充按钮?

    我正在用 Java JavaFX 编写一个 星际迷航 游戏 我的想法是主游戏屏幕是一个 10x10 的按钮网格面板 所有游戏部件 企业 克林贡 行星等 都将在按钮中显示为图标 这样 您可以单击一个空间对象来选择它 扭曲到它 射击它等等 当然
  • HttpWebRequest 与 HttpClient

    我有一段代码可以使用HttpWeb请求 and HttpWeb响应但我想将其转换为使用Http客户端 and Http响应消息 这是有效的代码块 HttpWebRequest request HttpWebRequest HttpWebRe
  • 为 OS X 构建虚拟相机

    我需要在 Skype 等程序中获取合成生成的视频流 音频部分很简单 有一个项目叫音花 https code google com p soundflower 这是一个适配器 它在一侧呈现虚拟音频目标设备 在另一侧呈现视频源 我正在为 OSX
  • 使用 Qt 显示 ubuntu (linux) 通知

    我正在使用 Qt 中的 Phonon 多媒体框架 它会弹出一条消息 就像改变音量时弹出的音量通知消息 因为我的音频设备尚未完全配置 是否可以从 Qt 启动我自己的通知 请看上图 非常感谢 AFAIK 使用 libnotify 是可行的方法
  • 如何获取最接近的元素id属性

    我试图找到最接近的具有 id 属性的元素并获取id 该元素可以是 p p div 或其他元素 我努力了 element test closest div id attr id 但只有当元素是 a 时它才会获取 iddiv 我想变得更加普遍
  • 为什么不读/写其内容的结构体的方法仍然会导致竞争情况?

    From 戴夫 切尼博客 http dave cheney net 2015 11 18 wednesday pop quiz spot the race 以下代码显然会导致竞争情况 只需更改即可解决func RPC version int