Go 循环中的互斥导致意外输出
我有一段过于简单的代码(或在这里) 从输出来看,我对以下几点感到惊讶:Go 循环中的互斥导致意外输出,go,concurrency,Go,Concurrency,我有一段过于简单的代码(或在这里) 从输出来看,我对以下几点感到惊讶: 对于j 对于j 对于i=1,只有3个值,而不是4个值 我可以理解缺少“1”的原因,因为变量在写入之前是递增的 有人能解释一下吗。和3 在循环中关闭变量,然后在单独的线程中运行闭包,而这些变量会继续更改。当您这样做时,请期待意外的结果-例如,您会看到5s,因为j在上一次迭代中增加到5,这会导致循环结束,但j仍保留5,单独的线程可以读取该值。它与互斥无关;这是变量的跨线程共享。如果您使用: go func(i,j int) {
j
j
有人能解释一下吗。和3 在循环中关闭变量,然后在单独的线程中运行闭包,而这些变量会继续更改。当您这样做时,请期待意外的结果-例如,您会看到5s,因为
j
在上一次迭代中增加到5,这会导致循环结束,但j
仍保留5,单独的线程可以读取该值。它与互斥无关;这是变量的跨线程共享。如果您使用:
go func(i,j int) {
fmt.Printf("%d + %d = %d\n", i, j, j+i)
mutex.Unlock()
}(i,j)
然后它将在goroutine启动时传入
i
和j
的值,后续迭代不会影响它:执行此操作时:
go func() {
fmt.Printf("%d + %d = %d\n", i, j, j+i)
mutex.Unlock()
}()
当前goroutine生成另一个循环,该循环增加j
增量发生在printf之前,这就是为什么我们甚至认为函数是在调用时调用的j
是<5
在函数有时间打印值之前,它可以增加到5。换句话说,您的程序运行方式如下:
- 进入循环
- 锁互斥
- 调用func()
- 增量j
- 打印值
- 解锁互斥锁
解决方法是将值按值传递给函数,而不是在整个goroutine中共享它们。请注意,您缺少最终的
4+4
,因为您没有等待最后一个goroutine完成。我知道将I
和j
作为函数参数传递在这里会有所帮助。我缺少循环的基础,即先递增该变量,然后检查条件。这就解释了5s
go func(i,j int) {
fmt.Printf("%d + %d = %d\n", i, j, j+i)
mutex.Unlock()
}(i,j)
go func() {
fmt.Printf("%d + %d = %d\n", i, j, j+i)
mutex.Unlock()
}()