欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

loopvar 改变不同版本的影响--并发性--请看另一个例子

最编程 2024-04-12 21:26:59
...
package main

import (
	"fmt"
	"runtime"
	"sync"
)

func main() {
	fmt.Println("golang version:", runtime.Version())
	concurrencyDemo()
}

func concurrencyDemo() {
	var wg sync.WaitGroup
	wg.Add(5)
	for i := 0; i < 5; i++ {
		go func() {
			defer wg.Done()
			fmt.Println(i)
		}()
	}
}

这个例子其实很简单,使用waitGroup来控制协程的数量和协程的结束。协程中只是打印循环变量i

golang 1.21的运行结果

go run -race demo/concurrency2.go
golang version: go1.21.5
5
5
==================
WARNING: DATA RACE
Read at 0x00c000120028 by goroutine 9:
  main.concurrencyDemo.func1()
      /home/lfeng/GolandProjects/golang101/demo/concurrency2.go:20 +0xaf

Previous write at 0x00c000120028 by main goroutine:
  main.concurrencyDemo()
      /home/lfeng/GolandProjects/golang101/demo/concurrency2.go:17 +0xa4
  main.main()
      /home/lfeng/GolandProjects/golang101/demo/concurrency2.go:11 +0xc4

Goroutine 9 (running) created at:
  main.concurrencyDemo()
      /home/lfeng/GolandProjects/golang101/demo/concurrency2.go:18 +0x85
  main.main()
      /home/lfeng/GolandProjects/golang101/demo/concurrency2.go:11 +0xc4
==================
5
5
5
Found 1 data race(s)
exit status 66

golang 1.22运行结果

go run -race demo/concurrency2.go
golang version: go1.22.1
2
1
4
3
0

发现1.21存在data race,但是1.22是不存在data race的

解决方法

go func增加参数传递循环的i
修改后的代码

package main

import (
	"fmt"
	"runtime"
	"sync"
)

func main() {
	fmt.Println("golang version:", runtime.Version())
	concurrencyDemo()
}

func concurrencyDemo() {
	var wg sync.WaitGroup
	wg.Add(5)
	for i := 0; i < 5; i++ {
		go func(i int) {
			defer wg.Done()
			fmt.Println(i)
		}(i)
	}
}

修改后的代码也不会存在data race

推荐阅读