++运算符需要互斥吗? 看来,当不使用互斥锁时,我会丢失一些数据,但是通过逻辑++只能将+1值添加到当前值,所以即使顺序不正确,总共还是要运行1000次吗? 示例:
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
i := 0
for r := 0; r < 1000; r++ {
wg.Add(1)
go func() {
i++
fmt.Println(i)
wg.Done()
}()
}
wg.Wait()
fmt.Printf("%d Done", i)
}
答案 0 :(得分:2)
要“仅将1添加到当前值”,计算机需要读取当前值,将其添加1,然后 write 返回新值。显然订购很重要;标准示例是:
Thread A Thread B
Read: 5
Read: 5
+1 = 6
+1 = 6
Write: 6
Write: 6
该值从5开始,两个执行线程各加一个,结果为6(应为7),因为B的读取发生在A的写入之前。
但是这里有一个更重要的误解:很多人认为在比赛中,代码要么读取旧值,要么读取新值。 不能保证。这可能是大多数时间发生的情况。可能是在您的计算机上一直在发生,使用当前版本的编译器等。但是actually it's possible对于以不安全/不友好的方式访问数据以生成任何结果,甚至是完整的垃圾。如果引发种族,则无法保证您从变量中读取的值对应于曾经具有的任何值。
答案 1 :(得分:0)
只需将+1值添加到当前值
不,不是“只是添加”。是
看看如何与多个并发参与者一起打破?
如果要原子增量,请签出sync/atomic。示例:https://gobyexample.com/atomic-counters