golang程序中并发会引起并发竞争,一起没理解,为什么说两个goroutine访问共享资源会引发竞争态,我的理解如果只使用一个逻辑处理器本质上不就是同一时间只有一个goroutine在跑吗,为什么会引发竞争态呢,做了如下实验,确实存在竞争态
package main
import (
"fmt"
"runtime"
"sync"
// "sync/atomic"
)
var (
counter int64
wg sync.WaitGroup
)
func main() {
wg.Add(2)
go inCounter("A")
go inCounter("B")
wg.Wait()
fmt.Println("Final Counter:", counter)
}
func inCounter(prefix string) {
defer wg.Done()
for count := 0; count < 2; count++ {
// atomic.AddInt64(&counter, 1)
counter++
fmt.Println(prefix, " excute Counter:", counter)
runtime.Gosched()
}
}
这段程序我多次执行,有一次结果是这样的:
B excute Counter: 1
B excute Counter: 2
A excute Counter: 1
A excute Counter: 3
Final Counter: 3
这结果完全不正确
所以它的执行顺序可能是这样的
1. B 执行完 couter++ 这是 couter = 1
2. A开始读取couter的值(1)
3. B 执行完 couter++ counter ==2 (执行完成)
4. A 执行完 couter+1 此时 couter == 2
5. A 执行完couter++ 此时couter=3
所以本质上是couter++ 存在读取和赋值的过程,就是goroutine A刚读取了couter,将要赋值时,被goroutineB赋值了,这时它的赋值就失去了。 所以它需要加锁,使用原子锁将update couter 整个过程锁住。
package main
import (
"fmt"
"runtime"
"sync"
"sync/atomic"
)
var (
counter int64
wg sync.WaitGroup
)
func main() {
wg.Add(2)
go inCounter("A")
go inCounter("B")
wg.Wait()
fmt.Println("Final Counter:", counter)
}
func inCounter(prefix string) {
defer wg.Done()
for count := 0; count < 2; count++ {
atomic.AddInt64(&counter, 1)
// counter++
fmt.Println(prefix, " excute Counter:", counter)
runtime.Gosched()
}
}