需要同步吗?

huangapple go评论78阅读模式
英文:

Is synchronization required?

问题

我在对象内部定义了一个变量(r.something)。

func (r *Runner) init() {
  r.something = make(map[string]int)
  r.something["a"]=1

  go r.goroutine()
}

r.goroutine() 在没有同步的情况下使用了 r.something 中存储的值。
除了 r.goroutine() 之外,没有其他人会读取/写入这个值。

在没有同步的情况下这样做是否安全?

换句话说:我想在 goroutine 开始之前从其他地方初始化的地方重用某些变量。这样安全吗?

附加问题:
r.goroutine() 完成后,我希望能够从其他地方使用 r.something(与其他 goroutine 的读写不重叠)。这样也安全吗?

英文:

I defined a variable (r.something) inside an object

func (r *Runner) init() {
  r.something = make(map[string]int)
  r.something["a"]=1

  go r.goroutine()
}

while r.goroutine uses value stored in r.something with no synchronization.
Nobody else is going to read/write this value except r.goroutine()

Is it safe to do without synchronization?

In other words: I want to reuse some variable from a goroutine initialized somewhere else before goroutine start. Is that safe?

Additional question:
After r.goroutine() finishes I want to be able to use r.something from somewhere else(without read/write overlap with other goroutines). Is it safe too?

答案1

得分: 5

当然,这是安全的,否则在Go中进行编程可能会成为一场噩梦(或者至少不那么愉快)。Go内存模型是一篇有趣的文章。

创建协程是一个同步点。有一个非常类似于你的例子:

var a string

func f() {
    print(a)
}

func hello() {
    a = "hello, world"
    go f()
}

有以下注释:

调用hello将在将来的某个时间点(可能在hello返回之后)打印"hello, world"。

这是因为:

启动新的goroutine的go语句发生在goroutine的执行开始之前。

这里的关键词是"before",它意味着在一个线程中创建协程必须与其启动(可能在另一个线程中)同步,因此对变量"a"的写操作必须对新的协程可见。

英文:

Of course this is safe, otherwise programming in Go might be a nightmare (or at least much less pleasant). The Go Memory Model is an interesting piece to read.

The routine creation is a synchronisation point. There is an example very similar to yours:

var a string

func f() {
	print(a)
}

func hello() {
	a = "hello, world"
	go f()
}

With the following comment:
> calling hello will print "hello, world" at some point in the future (perhaps after hello has returned).

This is because:

> The go statement that starts a new goroutine happens before the goroutine's execution begins.

The word before is crucial here as it implies routine creation (in one thread) must be synchronised with its start (possibly in other thread), so writes to a must be visible by the new routine.

答案2

得分: 3

如果没有不同的go-routines之间可能发生读写操作重叠的情况,那么你是正确的:不需要进行任何同步。

正如你提到的,在你的go-routine开始之前,该变量已经被初始化,所以你是安全的。

英文:

If there is no situation where an overlap of read and write operations by different go-routines may occur on this variable, then you are right: there is no need for any synchonization.

As you have mentioned that the variable was initialized before your go-routine started, you are in fact safe.

答案3

得分: 1

是的,它是安全的。根据Go内存模型

  • 启动新goroutine的go语句发生在goroutine执行开始之前
  • 在单个goroutine内,happens-before顺序是程序所表达的顺序

这意味着在启动goroutine之前对变量所做的所有更改在该goroutine内是可见的。

对于你的附加问题的回答是:这取决于情况。通常,如果r.goroutine()修改了r.something,并且你想从另一个goroutine中读取它,你需要使用同步机制。

英文:

Yes, it is safe. According to Go Memory Model:

  • the go statement that starts a new goroutine happens before the goroutine's execution begins
  • within a single goroutine, the happens-before order is the order expressed by the program

This means that all changes to variables that you made before starting a goroutine are visible inside this goroutine.

Answer to your additional question: it depends. Generally if r.goroutine() modified r.something and you want to read it from another goroutine you need to use synchronisation.

huangapple
  • 本文由 发表于 2015年8月12日 18:51:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/31963075.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定