登录
首页 >  Golang >  Go问答

指针接收器和非指针接收器的数据竞争差异

来源:stackoverflow

时间:2024-03-01 11:24:24 258浏览 收藏

哈喽!大家好,很高兴又见面了,我是golang学习网的一名作者,今天由我给大家带来一篇《指针接收器和非指针接收器的数据竞争差异》,本文主要会讲到等等知识点,希望大家一起学习进步,也欢迎大家关注、点赞、收藏、转发! 下面就一起来看看吧!

问题内容

我在使用 -race 标志进行测试期间发现了数据争用。更新结构并从结构方法读取值时发生数据竞争。 后来我发现将方法从非指针接收器更改为指针接收器可以解决数据竞争。但我不明白原因。谁能解释一下原因吗?

package main

import (
    "fmt"
    "testing"
)

type teststruct struct {
    display    bool
    othervalue int
}

func (t teststruct) display() bool {
    return t.display
}

func (t *teststruct) displayp() bool {
    return t.display
}

func testnonpointerrecevier(t *testing.t) {
    v := &teststruct{
        display: true,
    }

    go func() {
        v.othervalue = 1
    }()
    go func() {
        fmt.println(v.display())
    }()
}

func testpointerrecevier(t *testing.t) {
    v := &teststruct{
        display: true,
    }

    go func() {
        v.othervalue = 1
    }()
    go func() {
        fmt.println(v.displayp())
    }()
}

使用指针接收器方法没有错误

go test -race -run ^testpointerrecevier$
true
pass
ok      _/users/xxxxx/projects/golang/datarace  0.254s

使用非指针接收器方法时出现此错误

go test -race -run ^TestNonPointerRecevier$
==================
WARNING: DATA RACE
Read at 0x00c00001c2c8 by goroutine 9:
  _/Users/xxxxx/projects/golang/datarace.TestNonPointerRecevier.func2()
      /Users/xxxxx/projects/golang/datarace/main_test.go:30 +0x47

Previous write at 0x00c00001c2c8 by goroutine 8:
  _/Users/xxxxx/projects/golang/datarace.TestNonPointerRecevier.func1()
      /Users/xxxxx/projects/golang/datarace/main_test.go:27 +0x3e

Goroutine 9 (running) created at:
  _/Users/xxxxx/projects/golang/datarace.TestNonPointerRecevier()
      /Users/xxxxx/projects/golang/datarace/main_test.go:29 +0xba
  testing.tRunner()
      /usr/local/Cellar/go/1.15.6/libexec/src/testing/testing.go:1123 +0x202

Goroutine 8 (finished) created at:
  _/Users/xxxxx/projects/golang/datarace.TestNonPointerRecevier()
      /Users/xxxxx/projects/golang/datarace/main_test.go:26 +0x98
  testing.tRunner()
      /usr/local/Cellar/go/1.15.6/libexec/src/testing/testing.go:1123 +0x202
==================
true
FAIL
exit status 1
FAIL    _/Users/xxxxx/projects/golang/datarace  0.103s

解决方案


当方法的接收者值是结构体(而不是指向结构体的指针)时,将复制完整的结构体以按值传递给该方法。
因此,调用 v.Display() 会隐式读取字段 OtherValue (在复制结构时),因此出现竞争条件。

另一方面,当使用指针时,仅复制指针,并且与 v.OtherValue 同时访问 v.display 不会触发竞争条件。

今天关于《指针接收器和非指针接收器的数据竞争差异》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注golang学习网公众号!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>